Motr  M0
rconfc_link_fom.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 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_CONF
24 
25 #include "lib/trace.h"
26 
27 #include "lib/finject.h" /* M0_FI_ENABLED */
28 #include "rpc/conn.h" /* m0_rpc_conn_terminate */
29 #include "rpc/rpc.h" /* m0_rpc__down_timeout */
30 #include "rpc/rpc_opcodes.h"
31 #include "rpc/session.h" /* m0_rpc_session_terminate */
32 #include "conf/confc.h"
33 #include "conf/rconfc.h"
34 #include "conf/rconfc_internal.h"
35 #include "conf/rconfc_link_fom.h"
36 
37 /*
38  * rconfc_herd_link_fini() being located in conf/rconfc.c is exposed by this for
39  * rconfc_link_fom_fini().
40  */
41 M0_INTERNAL void rconfc_herd_link_fini(struct rconfc_link *lnk);
42 
44  [M0_RLF_INIT] = {
46  .sd_name = "M0_RLF_INIT",
48  },
50  .sd_flags = 0,
51  .sd_name = "M0_RLF_SESS_WAIT_IDLE",
53  },
55  .sd_flags = 0,
56  .sd_name = "M0_RLF_SESS_TERMINATING",
58  },
60  .sd_flags = 0,
61  .sd_name = "M0_RLF_CONN_TERMINATING",
62  .sd_allowed = M0_BITS(M0_RLF_FINI)
63  },
64  [M0_RLF_FINI] = {
65  .sd_flags = M0_SDF_TERMINAL,
66  .sd_name = "M0_RLF_FINI",
67  .sd_allowed = 0
68  },
69 };
70 
71 static const struct m0_sm_conf rconfc_link_fom_sm_conf = {
72  .scf_name = "rconfc_link FOM state machine",
73  .scf_nr_states = ARRAY_SIZE(rconfc_link_fom_state_descr),
74  .scf_state = rconfc_link_fom_state_descr,
75 };
76 
78 
79 static int rconfc_link_fom_create(struct m0_fop *fop, struct m0_fom **out,
80  struct m0_reqh *reqh)
81 {
82  M0_ENTRY();
83  M0_IMPOSSIBLE("Expected to never be called");
84  return M0_RC(0);
85 }
86 
88 {
91  lnk->rl_fom_clink.cl_chan = NULL;
92 }
93 
94 static void rconfc_link_fom_fini(struct m0_fom *fom)
95 {
96  struct rconfc_link *lnk = M0_AMB(lnk, fom, rl_fom);
97 
98  M0_ENTRY("lnk=%p state=%d ep=%s ",
99  lnk, lnk->rl_state, lnk->rl_confd_addr);
100  m0_fom_fini(fom);
104  /*
105  * Note: rl_state must be set to CONFC_DEAD only after link finalisation
106  * to not prevent the link from correct cleanup.
107  */
108  lnk->rl_state = CONFC_DEAD;
109  /*
110  * XXX: The callback is only for UT
111  */
112  if (lnk->rl_on_state_cb != NULL)
113  lnk->rl_on_state_cb(lnk);
114  M0_SET0(&lnk->rl_fom);
115  lnk->rl_fom_queued = false;
120  M0_LEAVE();
121 }
122 
123 static size_t rconfc_link_fom_locality(const struct m0_fom *fom)
124 {
125  struct rconfc_link *lnk = M0_AMB(lnk, fom, rl_fom);
126 
127  return lnk->rl_confd_fid.f_key;
128 }
129 
131 {
132  struct rconfc_link *lnk = M0_AMB(lnk, clink, rl_fom_clink);
133  struct m0_rpc_session *sess = m0_confc2sess(&lnk->rl_confc);
134 
135  if (!M0_IN(sess->s_sm.sm_state, (M0_RPC_SESSION_IDLE,
137  return true;
138  m0_fom_wakeup(&lnk->rl_fom);
139  return false;
140 }
141 
143 {
144  struct rconfc_link *lnk = M0_AMB(lnk, clink, rl_fom_clink);
145  struct m0_rpc_session *sess = m0_confc2sess(&lnk->rl_confc);
146 
147  if (!M0_IN(sess->s_sm.sm_state, (M0_RPC_SESSION_TERMINATED,
149  return true;
150  m0_fom_wakeup(&lnk->rl_fom);
151  return false;
152 }
153 
155 {
156  struct rconfc_link *lnk = M0_AMB(lnk, clink, rl_fom_clink);
157  struct m0_rpc_conn *conn = m0_confc2conn(&lnk->rl_confc);
158 
161  return true;
162  m0_fom_wakeup(&lnk->rl_fom);
163  return false;
164 }
165 
167  int phase)
168 {
169  struct m0_rpc_session *sess = m0_confc2sess(&lnk->rl_confc);
170  struct m0_rpc_conn *conn = m0_confc2conn(&lnk->rl_confc);
171  struct m0_chan *chan[] = {
172  [M0_RLF_INIT] = &sess->s_sm.sm_chan,
175  };
176  m0_chan_cb_t cb[] = {
180  };
181  /*
182  * Ensure that link is cleaned up before next initialization
183  */
185  m0_clink_init(&lnk->rl_fom_clink, cb[phase]);
186  m0_clink_add_lock(chan[phase], &lnk->rl_fom_clink);
187 }
188 
189 static int rconfc_link_fom_tick(struct m0_fom *fom)
190 {
191  struct rconfc_link *lnk = M0_AMB(lnk, fom, rl_fom);
192  struct m0_rpc_session *sess = m0_confc2sess(&lnk->rl_confc);
193  struct m0_rpc_conn *conn = m0_confc2conn(&lnk->rl_confc);
194  int phase = m0_fom_phase(fom);
195  int rc;
196 
197  M0_ENTRY();
198 
199  switch (phase) {
200  case M0_RLF_INIT:
201  /*
202  * In case confc is not online, it is safe to finalise the link
203  * right away.
204  */
205  if (!m0_confc_is_inited(&lnk->rl_confc) ||
206  !m0_confc_is_online(&lnk->rl_confc)) {
208  return M0_FSO_WAIT;
209  }
211  /*
212  * It turns out the confc needs to quiesce the session prior to
213  * going on with its termination.
214  */
215  if (M0_IN(sess->s_sm.sm_state, (M0_RPC_SESSION_IDLE,
217  return M0_FSO_AGAIN;
218  rconfc_herd_link_fom_wait_on(lnk, phase);
219  break;
220 
222  rconfc_herd_link_fom_wait_on(lnk, phase);
224  /*
225  * The session may appear to be already failed due to external
226  * reasons. If so, go straight to disconnection phase.
227  */
228  if (sess->s_sm.sm_state == M0_RPC_SESSION_FAILED) {
229  M0_LOG(M0_DEBUG, "session=%p found failed", sess);
230  return M0_FSO_AGAIN;
231  }
232  /* Break rpc session */
233  if (M0_FI_ENABLED("sess_fail"))
234  m0_fi_enable_once("m0_rpc_session_terminate",
235  "fail_allocation");
237  if (rc != 0) {
238  M0_LOG(M0_ERROR, "session=%p, rc=%d", sess, rc);
240  }
241  break;
242 
245  m0_rpc_session_fini(sess);
246  /* Break rpc connection */
247  rconfc_herd_link_fom_wait_on(lnk, phase);
249  if (M0_FI_ENABLED("conn_fail"))
250  m0_fi_enable_once("m0_rpc_conn_terminate",
251  "fail_allocation");
253  if (rc != 0) {
254  M0_LOG(M0_ERROR, "conn=%p, rc=%d", conn, rc);
256  }
257  break;
258 
262  /* Finalise FOM */
264  break;
265  }
266 
267  return M0_FSO_WAIT;
268 }
269 
272 };
273 
276  .fo_tick = rconfc_link_fom_tick,
277  .fo_home_locality = rconfc_link_fom_locality
278 };
279 
280 M0_INTERNAL int m0_rconfc_mod_init(void)
281 {
283 
287  return 0;
288 }
289 
290 M0_INTERNAL void m0_rconfc_mod_fini(void)
291 {
292 }
293 
294 #undef M0_TRACE_SUBSYSTEM
295 
296 /*
297  * Local variables:
298  * c-indentation-style: "K&R"
299  * c-basic-offset: 8
300  * tab-width: 8
301  * fill-column: 80
302  * scroll-step: 1
303  * End:
304  */
M0_INTERNAL void m0_fom_wakeup(struct m0_fom *fom)
Definition: fom.c:532
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
#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
Definition: sm.h:350
M0_INTERNAL void rconfc_herd_link_cleanup(struct rconfc_link *lnk)
Definition: rconfc.c:1572
M0_INTERNAL struct m0_rpc_conn * m0_confc2conn(struct m0_confc *confc)
Definition: confc.c:1045
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
int(* fto_create)(struct m0_fop *fop, struct m0_fom **out, struct m0_reqh *reqh)
Definition: fom.h:650
#define M0_BITS(...)
Definition: misc.h:236
M0_INTERNAL void m0_rpc_session_fini(struct m0_rpc_session *session)
Definition: session.c:292
M0_INTERNAL m0_time_t m0_rpc__down_timeout(void)
Definition: rpc.c:322
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
m0_fom_phase
Definition: fom.h:372
M0_INTERNAL int m0_rpc_conn_terminate(struct m0_rpc_conn *conn, m0_time_t abs_timeout)
Definition: conn.c:1009
struct m0_sm c_sm
Definition: conn.h:322
return M0_RC(rc)
#define M0_ENTRY(...)
Definition: trace.h:170
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
void m0_fom_fini(struct m0_fom *fom)
Definition: fom.c:1324
M0_INTERNAL int m0_rpc_session_terminate(struct m0_rpc_session *session, m0_time_t abs_timeout)
Definition: session.c:622
#define M0_ASSERT(cond)
const char * scf_name
Definition: sm.h:352
struct m0_mutex rc_herd_lock
Definition: rconfc.h:410
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
M0_INTERNAL bool m0_confc_is_online(const struct m0_confc *confc)
Definition: confc.c:453
struct m0_chan rc_herd_chan
Definition: rconfc.h:416
M0_INTERNAL void rconfc_herd_link_fini(struct rconfc_link *lnk)
Definition: rconfc.c:1433
M0_INTERNAL void m0_rconfc_lock(struct m0_rconfc *rconfc)
Definition: rconfc.c:2841
Definition: reqh.h:94
M0_INTERNAL void m0_clink_cleanup(struct m0_clink *link)
Definition: chan.c:310
Definition: dump.c:103
Definition: chan.h:229
struct m0_rpc_conn conn
Definition: fsync.c:96
M0_INTERNAL bool m0_confc_is_inited(const struct m0_confc *confc)
Definition: confc.c:448
static struct m0_clink clink[RDWR_REQUEST_MAX]
struct m0_sm s_sm
Definition: session.h:325
bool(* m0_chan_cb_t)(struct m0_clink *link)
Definition: chan.h:176
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
Definition: fom.h:481
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_chan chan[RDWR_REQUEST_MAX]
#define M0_FI_ENABLED(tag)
Definition: finject.h:231
uint64_t f_key
Definition: fid.h:40
struct m0_chan sm_chan
Definition: sm.h:331
struct m0_reqh_service_type m0_rpc_service_type
Definition: service.c:120
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
static struct m0_fop * fop
Definition: item.c:57
static void m0_fi_enable_once(const char *func, const char *tag)
Definition: finject.h:301
void(* fo_fini)(struct m0_fom *fom)
Definition: fom.h:657
M0_INTERNAL struct m0_rpc_session * m0_confc2sess(struct m0_confc *confc)
Definition: confc.c:1050
#define out(...)
Definition: gen.c:41
void m0_fom_phase_set(struct m0_fom *fom, int phase)
Definition: fom.c:1688
uint32_t sm_state
Definition: sm.h:307
M0_INTERNAL void m0_chan_broadcast(struct m0_chan *chan)
Definition: chan.c:172
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
M0_INTERNAL void m0_rpc_conn_fini(struct m0_rpc_conn *conn)
Definition: conn.c:558
Definition: fop.h:79
#define M0_IMPOSSIBLE(fmt,...)