Motr  M0
drlink.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2021 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 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_DTM0
23 #include "lib/trace.h"
24 #include "addb2/identifier.h" /* M0_AVI_FOM_TO_TX */
25 #include "dtm0/fop.h" /* dtm0_req_fop */
26 #include "dtm0/service.h" /* m0_dtm0_service */
27 #include "dtm0/svc_internal.h" /* dtm0_process */
28 #include "lib/coroutine.h" /* m0_co API */
29 #include "lib/memory.h" /* M0_ALLOC_PTR */
30 #include "reqh/reqh.h" /* m0_reqh fields */
31 #include "rpc/rpc.h" /* m0_rpc_item_post */
32 #include "rpc/rpc_machine.h" /* m0_rpc_machine */
33 #include "rpc/rpc_opcodes.h" /* M0_DTM0_{RLINK,REQ}_OPCODE */
34 
35 struct drlink_fom {
36  struct m0_fom df_gen;
38  struct m0_be_op *df_op;
39  struct m0_fid df_tgt;
40  struct m0_fop *df_rfop;
44  uint64_t df_parent_sm_id;
45 };
46 
47 static struct drlink_fom *fom2drlink_fom(struct m0_fom *fom)
48 {
49  struct drlink_fom *df;
50  M0_PRE(fom != NULL);
51  return M0_AMB(df, fom, df_gen);
52 }
53 
54 static size_t drlink_fom_locality(const struct m0_fom *fom)
55 {
56  static size_t loc;
57  /*
58  * At this moment, any locality can be the home locality
59  * for this kind of FOM.
60  */
61  return loc++;
62 }
63 
64 static void drlink_fom_fini(struct m0_fom *fom);
65 static int drlink_fom_tick(struct m0_fom *fom);
66 
67 static const struct m0_fom_ops drlink_fom_ops = {
69  .fo_tick = drlink_fom_tick,
70  .fo_home_locality = drlink_fom_locality
71 };
72 
74 static const struct m0_fom_type_ops drlink_fom_type_ops = {};
75 const static struct m0_sm_conf drlink_fom_conf;
76 
77 M0_INTERNAL int m0_dtm0_rpc_link_mod_init(void)
78 {
84  return 0;
85 }
86 
87 M0_INTERNAL void m0_dtm0_rpc_link_mod_fini(void)
88 {
89 }
90 
91 /* Create a deep copy of the given request. */
92 static struct dtm0_req_fop *dtm0_req_fop_dup(const struct dtm0_req_fop *src)
93 {
94  int rc;
95  struct dtm0_req_fop *dst;
96 
98  if (dst == NULL)
99  return NULL;
100 
101  rc = m0_dtm0_tx_desc_copy(&src->dtr_txr, &dst->dtr_txr);
102  if (rc != 0) {
103  M0_ASSERT(rc == -ENOMEM);
104  m0_free(dst);
105  return NULL;
106  }
107 
108  rc = m0_buf_copy(&dst->dtr_payload, &src->dtr_payload);
109  if (rc != 0) {
110  m0_dtm0_tx_desc_fini(&dst->dtr_txr);
111  m0_free(dst);
112  return NULL;
113  }
114 
115  dst->dtr_msg = src->dtr_msg;
116 
117  return dst;
118 }
119 
120 static void dtm0_req_fop_fini(struct dtm0_req_fop *req)
121 {
122  m0_dtm0_tx_desc_fini(&req->dtr_txr);
123  m0_buf_free(&req->dtr_payload);
124 }
125 
126 static int drlink_fom_init(struct drlink_fom *fom,
127  struct m0_dtm0_service *svc,
128  struct m0_be_op *op,
129  const struct m0_fid *tgt,
130  const struct dtm0_req_fop *req,
131  const struct m0_fom *parent_fom,
132  bool wait_for_ack)
133 {
134  struct m0_rpc_machine *mach;
135  struct m0_reqh *reqh;
136  struct dtm0_req_fop *owned_req;
137  struct m0_fop *fop;
138 
139  M0_ENTRY();
140  M0_PRE(fom != NULL);
141  M0_PRE(svc != NULL);
142  M0_PRE(req != NULL);
144 
145  reqh = svc->dos_generic.rs_reqh;
146  mach = m0_reqh_rpc_mach_tlist_head(&reqh->rh_rpc_machines);
147 
148  owned_req = dtm0_req_fop_dup(req);
149  if (owned_req == NULL)
150  return M0_ERR(-ENOMEM);
151 
152  fop = m0_fop_alloc(req->dtr_msg == DTM_REDO ?
155  owned_req, mach);
156  if (fop == NULL) {
157  dtm0_req_fop_fini(owned_req);
158  m0_free(owned_req);
159  return M0_ERR(-ENOMEM);
160  }
161 
162  /*
163  * When ACK is not required, the FOM may be released before
164  * the received callback is triggered.
165  * See ^1 in ::dtm0_rlink_rpc_item_reply_cb.
166  */
167  fop->f_opaque = wait_for_ack ? fom : NULL;
168 
170  NULL, NULL, reqh);
171 
172  /* TODO: can we use fom->fo_fop instead? */
173  fom->df_rfop = fop;
174  fom->df_svc = svc;
175  fom->df_op = op;
176  fom->df_tgt = *tgt;
177  fom->df_wait_for_ack = wait_for_ack;
178  fom->df_parent_sm_id = m0_sm_id_get(&parent_fom->fo_sm_phase);
179 
180  m0_co_context_init(&fom->df_co);
181  m0_co_op_init(&fom->df_co_op);
182 
183  if (op != NULL)
185 
186  return M0_RC(0);
187 }
188 
189 static void drlink_fom_fini(struct m0_fom *fom)
190 {
191  struct drlink_fom *df = fom2drlink_fom(fom);
193  m0_co_op_fini(&df->df_co_op);
194  m0_fom_fini(fom);
195  m0_free(fom);
196 }
197 
198 static void co_long_write_lock(struct m0_co_context *context,
199  struct m0_long_lock *lk,
200  struct m0_long_lock_link *link,
201  int next_phase)
202 {
203  int outcome;
204  M0_CO_REENTER(context);
206  next_phase));
207  M0_CO_YIELD_RC(context, outcome);
208 }
209 
210 static void co_rpc_link_connect(struct m0_co_context *context,
211  struct m0_rpc_link *rlink,
212  struct m0_fom *fom,
213  int next_phase)
214 {
215  M0_CO_REENTER(context);
216 
217  m0_chan_lock(&rlink->rlk_wait);
218  m0_fom_wait_on(fom, &rlink->rlk_wait, &fom->fo_cb);
219  m0_chan_unlock(&rlink->rlk_wait);
220 
222  m0_fom_phase_set(fom, next_phase);
223 
224  M0_CO_YIELD_RC(context, M0_FSO_WAIT);
225 }
226 
227 static int find_or_add(struct m0_dtm0_service *dtms,
228  const struct m0_fid *tgt,
229  struct dtm0_process **out)
230 {
231  struct dtm0_process *process;
232  int rc = 0;
233 
234  M0_ENTRY();
236 
237  process = dtm0_service_process__lookup(&dtms->dos_generic, tgt);
238  if (process == NULL) {
239  rc = M0_ALLOC_PTR(process) == NULL ?
240  M0_ERR(-ENOMEM) :
241  dtm0_process_init(process, dtms, tgt);
242  if (rc != 0)
243  m0_free(process);
244  }
245 
246  if (rc == 0) {
247  M0_POST(process != NULL);
248  *out = process;
249  }
250  return M0_RC(rc);
251 }
252 
262 };
263 
265  [DRF_INIT] = {
266  .sd_name = "DRF_INIT",
267  .sd_allowed = M0_BITS(DRF_LOCKING, DRF_FAILED),
268  .sd_flags = M0_SDF_INITIAL,
269  },
270  /* terminal states */
271  [DRF_DONE] = {
272  .sd_name = "DRF_DONE",
273  .sd_allowed = 0,
274  .sd_flags = M0_SDF_TERMINAL,
275  },
276  /* failure states */
277  [DRF_FAILED] = {
278  .sd_name = "DRF_FAILED",
279  .sd_allowed = M0_BITS(DRF_DONE),
280  .sd_flags = M0_SDF_FAILURE,
281  },
282 
283  /* intermediate states */
284 #define _ST(name, allowed) \
285  [name] = { \
286  .sd_name = #name, \
287  .sd_allowed = allowed \
288  }
290  DRF_SENDING,
291  DRF_FAILED)),
293  DRF_FAILED)),
296  DRF_FAILED)),
298  DRF_FAILED)),
299 #undef _ST
300 };
301 
302 const static struct m0_sm_conf drlink_fom_conf = {
303  .scf_name = "m0_dtm0_drlink_fom",
304  .scf_nr_states = ARRAY_SIZE(drlink_fom_states),
305  .scf_state = drlink_fom_states,
306 };
307 
309 {
311 }
312 
314 {
315  struct m0_fop *reply = NULL;
316  struct drlink_fom *df = item2drlink_fom(item);
317  uint32_t req_opcode = m0_fop_opcode(m0_rpc_item_to_fop(item));
318 
319  M0_ENTRY("item=%p", item);
320 
321  M0_PRE(item != NULL);
322  M0_PRE(M0_IN(req_opcode, (M0_DTM0_REQ_OPCODE,
324 
325  if (m0_rpc_item_error(item) == 0) {
328  }
329 
330  /* ^1: df is NULL if we do not need to wait for the reply. */
331  if (df != NULL)
332  m0_co_op_done(&df->df_co_op);
333 
334  M0_LEAVE("reply=%p", reply);
335 }
336 
339 };
340 
341 static int dtm0_process_rlink_reinit(struct dtm0_process *proc,
342  struct drlink_fom *df)
343 {
345  const int max_in_flight = DTM0_MAX_RPCS_IN_FLIGHT;
346 
347  if (!M0_IS0(&proc->dop_rlink)) {
348  m0_rpc_link_fini(&proc->dop_rlink);
349  M0_SET0(&proc->dop_rlink);
350  }
351 
352  return m0_rpc_link_init(&proc->dop_rlink, mach, &proc->dop_rserv_fid,
353  proc->dop_rep, max_in_flight);
354 }
355 
356 static int dtm0_process_rlink_send(struct dtm0_process *proc,
357  struct drlink_fom *drf)
358 {
359  struct m0_fop *fop = drf->df_rfop;
360  struct m0_rpc_session *session = &proc->dop_rlink.rlk_sess;
361  struct m0_rpc_item *item = &fop->f_item;
362 
367 
368  if (drf->df_wait_for_ack)
369  m0_co_op_active(&drf->df_co_op);
370 
371  return m0_rpc_post(item);
372 }
373 
375 enum dpr_state {
382 };
383 
384 static enum dpr_state dpr_state_infer(struct dtm0_process *proc)
385 {
386  /*
387  * TODO:
388  * Observe the states of the following enitities:
389  * RPC connection
390  * RPC session
391  * Conf obj
392  * and then decide whether it is alive, dead or permanently dead.
393  *
394  * @verbatim
395  * if (conf_obj is ONLINE) {
396  * if (conn is ACTIVE && session is in (IDLE, BUSY))
397  * return ONLINE;
398  * else
399  * return TRANSIENT;
400  * } else
401  * return FAILED;
402  * @endverbatim
403  */
405  return DPR_ONLINE;
406 
407  return DPR_TRANSIENT;
408 }
409 
410 /*
411  * Establish a relation between a DTM message (carried by an RPC item),
412  * and a DTM RPC link FOM that was used to send this message:
413  * DRLINK FOM <-> RPC item.
414  */
415 static void drlink_addb_drf2item_relate(struct drlink_fom *drf)
416 {
417  const struct m0_rpc_item *item = &drf->df_rfop->f_item;
419  m0_sm_id_get(&item->ri_sm));
420 }
421 
422 /*
423  * Establish a relation between a FOM (for example, a CAS PUT FOM).
424  * and a DTM RPC link FOM that was created to send a DTM message:
425  * FOM <-> DRLINK FOM.
426  */
428 {
431 }
432 
433 #define F M0_CO_FRAME_DATA
434 static void drlink_coro_fom_tick(struct m0_co_context *context)
435 {
436  int rc = 0;
437  struct drlink_fom *drf = M0_AMB(drf, context, df_co);
438  struct m0_fom *fom = &drf->df_gen;
439 
440  M0_CO_REENTER(context,
441  struct m0_long_lock_link llink;
442  struct m0_long_lock_addb2 llock_addb2;
443  struct dtm0_process *proc;
444  );
445 
447 
449  rc = find_or_add(drf->df_svc, &drf->df_tgt, &F(proc));
450  /*
451  * Safety: it is safe to release the lock right here because
452  * ::dtm0_service_conns_term is supposed to be called only
453  * after all drlink FOMs have reached DRF_DONE state.
454  * There are no other places where processes get removed from the list.
455  */
457 
458  if (rc != 0)
459  goto out;
460 
461  m0_long_lock_link_init(&F(llink), fom, &F(llock_addb2));
462 
463  M0_CO_FUN(context, co_long_write_lock(context,
464  &F(proc)->dop_llock,
465  &F(llink),
466  DRF_LOCKING));
468 
469  if (dpr_state_infer(F(proc)) == DPR_TRANSIENT) {
470  rc = dtm0_process_rlink_reinit(F(proc), drf);
471  if (rc != 0)
472  goto unlock;
473  /*
474  * TODO handle network failure after link is connected, but
475  * before the message is successfully sent
476  */
477  M0_CO_FUN(context, co_rpc_link_connect(context,
478  &F(proc)->dop_rlink,
479  fom, DRF_CONNECTING));
480  }
481 
482  if (dpr_state_infer(F(proc)) == DPR_FAILED)
483  goto unlock;
484 
487  rc = dtm0_process_rlink_send(F(proc), drf);
488  if (rc != 0)
489  goto unlock;
490 
491  /* Safety: FOP (and item) can be released only in ::drlink_fom_fini. */
493 
494  if (drf->df_wait_for_ack) {
495  M0_CO_YIELD_RC(context,
498  m0_co_op_reset(&drf->df_co_op);
500  }
501 
502 unlock:
503  m0_long_write_unlock(&F(proc)->dop_llock, &F(llink));
504  m0_long_lock_link_fini(&F(llink));
505 out:
506  /* TODO handle the error */
507  if (rc != 0)
509  if (drf->df_op != NULL)
510  m0_be_op_done(drf->df_op);
511 
513 }
514 #undef F
515 
516 static int drlink_fom_tick(struct m0_fom *fom)
517 {
518  int rc;
519  struct m0_co_context *co = &fom2drlink_fom(fom)->df_co;
520 
521  M0_ENTRY("fom=%p", fom);
522 
523  M0_CO_START(co);
525  rc = M0_CO_END(co);
526 
527  M0_POST(M0_IN(rc, (0, M0_FSO_AGAIN, M0_FSO_WAIT)));
528  /*
529  * Zero means the coroutine has nothing more to do.
530  * Replace it with FSO_WAIT as per the convention (see fom_exec).
531  */
532  rc = rc ?: M0_FSO_WAIT;
533  return M0_RC(rc);
534 }
535 
536 M0_INTERNAL int m0_dtm0_req_post(struct m0_dtm0_service *svc,
537  struct m0_be_op *op,
538  const struct dtm0_req_fop *req,
539  const struct m0_fid *tgt,
540  const struct m0_fom *parent_fom,
541  bool wait_for_ack)
542 {
543  int rc;
544  struct drlink_fom *fom;
545 
546  M0_ENTRY();
547 
548  M0_ALLOC_PTR(fom);
549  if (fom == NULL)
550  return M0_ERR(-ENOMEM);
551 
552  rc = drlink_fom_init(fom, svc, op, tgt, req, parent_fom, wait_for_ack);
553 
554  if (rc == 0)
555  m0_fom_queue(&fom->df_gen);
556  else
557  m0_free(fom);
558 
559  return rc == 0 ? M0_RC(rc) : M0_ERR(rc);
560 }
561 
562 /*
563  * Local variables:
564  * c-indentation-style: "K&R"
565  * c-basic-offset: 8
566  * tab-width: 8
567  * fill-column: 80
568  * scroll-step: 1
569  * End:
570  */
M0_INTERNAL int m0_rpc_post(struct m0_rpc_item *item)
Definition: rpc.c:63
M0_INTERNAL void m0_long_lock_link_init(struct m0_long_lock_link *link, struct m0_fom *fom, struct m0_long_lock_addb2 *addb2)
Definition: fom_long_lock.c:66
uint32_t m0_fop_opcode(const struct m0_fop *fop)
Definition: fop.c:226
#define M0_PRE(cond)
char * dop_rep
Definition: svc_internal.h:66
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
M0_INTERNAL int dtm0_process_init(struct dtm0_process *proc, struct m0_dtm0_service *dtms, const struct m0_fid *rem_svc_fid)
Definition: service.c:421
enum m0_rpc_item_priority ri_prio
Definition: item.h:133
#define M0_FOM_LONG_LOCK_RETURN(rc)
#define NULL
Definition: misc.h:38
static struct m0_bufvec dst
Definition: xform.c:61
Definition: fop.h:50
Definition: sm.h:350
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
static struct io_request req
Definition: file.c:100
struct m0_reqh_service_type dtm0_service_type
Definition: service.c:60
M0_LEAVE()
M0_INTERNAL void m0_co_op_reset(struct m0_co_op *op)
Definition: coroutine.c:203
static enum named_outcome outcome(const struct put_del_ver_case *c)
Definition: client_ut.c:3746
struct m0_sm ri_sm
Definition: item.h:181
M0_INTERNAL void m0_co_op_init(struct m0_co_op *op)
Definition: coroutine.c:179
static struct m0_addb2_mach * mach
Definition: storage.c:42
M0_INTERNAL void m0_fom_wait_on(struct m0_fom *fom, struct m0_chan *chan, struct m0_fom_callback *cb)
Definition: fom.c:1490
#define M0_BITS(...)
Definition: misc.h:236
M0_INTERNAL void m0_long_write_unlock(struct m0_long_lock *lock, struct m0_long_lock_link *link)
#define M0_CO_START(context)
Definition: coroutine.h:157
M0_INTERNAL struct dtm0_process * dtm0_service_process__lookup(struct m0_reqh_service *reqh_dtm0_svc, const struct m0_fid *remote_dtm0)
Definition: service.c:149
M0_INTERNAL void m0_chan_lock(struct m0_chan *ch)
Definition: chan.c:68
static struct m0_rpc_session session
Definition: formation2.c:38
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
M0_ADDB2_ADD(M0_AVI_FS_CREATE, new_fid.f_container, new_fid.f_key, mode, rc)
#define M0_CO_END(context)
Definition: coroutine.h:167
static struct m0_rpc_item * item
Definition: item.c:56
return M0_RC(rc)
op
Definition: libdemo.c:64
#define M0_ENTRY(...)
Definition: trace.h:170
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
M0_INTERNAL bool m0_long_write_lock(struct m0_long_lock *lk, struct m0_long_lock_link *link, int next_phase)
struct m0_fid dop_rserv_fid
Definition: svc_internal.h:64
return M0_ERR(-EOPNOTSUPP)
#define M0_CO_YIELD_RC(context, rc)
Definition: coroutine.h:248
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
void m0_fom_fini(struct m0_fom *fom)
Definition: fom.c:1324
M0_INTERNAL void m0_co_op_fini(struct m0_co_op *op)
Definition: coroutine.c:188
struct m0_long_lock dop_llock
Definition: svc_internal.h:71
#define M0_ASSERT(cond)
const char * scf_name
Definition: sm.h:352
M0_INTERNAL bool m0_mutex_is_locked(const struct m0_mutex *mutex)
Definition: mutex.c:95
void m0_fom_phase_move(struct m0_fom *fom, int32_t rc, int phase)
Definition: fom.c:1699
M0_INTERNAL void m0_long_lock_link_fini(struct m0_long_lock_link *link)
Definition: fom_long_lock.c:76
M0_INTERNAL int m0_co_op_tick_ret(struct m0_co_op *op, struct m0_fom *fom, int next_state)
Definition: coroutine.c:226
struct m0_tl rh_rpc_machines
Definition: reqh.h:135
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
struct m0_rpc_item * ri_reply
Definition: item.h:163
void * f_opaque
Definition: fop.h:84
#define M0_POST(cond)
Definition: reqh.h:94
M0_INTERNAL void m0_be_op_done(struct m0_be_op *op)
Definition: stubs.c:104
Definition: dump.c:103
M0_INTERNAL void m0_buf_free(struct m0_buf *buf)
Definition: buf.c:55
struct m0_fop_type dtm0_redo_fop_fopt
Definition: fop.c:44
struct m0_rpc_link dop_rlink
Definition: svc_internal.h:60
M0_INTERNAL int m0_buf_copy(struct m0_buf *dest, const struct m0_buf *src)
Definition: buf.c:104
M0_INTERNAL void m0_chan_unlock(struct m0_chan *ch)
Definition: chan.c:73
M0_INTERNAL void m0_co_op_active(struct m0_co_op *op)
Definition: coroutine.c:210
M0_INTERNAL bool m0_long_is_write_locked(struct m0_long_lock *lock, const struct m0_fom *fom)
struct m0_mutex rs_mutex
Definition: reqh_service.h:249
void(* rio_replied)(struct m0_rpc_item *item)
Definition: item.h:300
#define M0_CO_FUN(context, function)
Definition: coroutine.h:183
M0_INTERNAL int m0_dtm0_tx_desc_copy(const struct m0_dtm0_tx_desc *src, struct m0_dtm0_tx_desc *dst)
Definition: tx_desc.c:76
Definition: fom.h:481
int32_t m0_rpc_item_error(const struct m0_rpc_item *item)
Definition: item.c:973
struct m0_pdclust_tgt_addr tgt
Definition: fd.c:110
struct m0_reqh reqh
Definition: rm_foms.c:48
M0_INTERNAL void m0_be_op_active(struct m0_be_op *op)
Definition: stubs.c:100
const char * sd_name
Definition: sm.h:383
Definition: fid.h:38
#define M0_IS0(obj)
Definition: misc.h:70
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
const struct m0_rpc_item_ops * ri_ops
Definition: item.h:149
M0_INTERNAL int m0_co_context_init(struct m0_co_context *context)
Definition: coroutine.c:130
struct m0_rpc_session * ri_session
Definition: item.h:147
static struct m0_net_test_service svc
Definition: service.c:34
void m0_fop_put_lock(struct m0_fop *fop)
Definition: fop.c:199
static struct m0_fop * fop
Definition: item.c:57
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
struct m0_sm fo_sm_phase
Definition: fom.h:522
void(* fo_fini)(struct m0_fom *fom)
Definition: fom.h:657
#define M0_CO_REENTER(context,...)
Definition: coroutine.h:205
#define out(...)
Definition: gen.c:41
void m0_fom_phase_set(struct m0_fom *fom, int phase)
Definition: fom.c:1688
M0_INTERNAL bool m0_fid_is_valid(const struct m0_fid *fid)
Definition: fid.c:96
struct m0_rpc_machine * ri_rmachine
Definition: item.h:160
Definition: op.h:74
static struct m0_dtm_oper_descr reply
Definition: transmit.c:94
M0_INTERNAL uint64_t m0_sm_id_get(const struct m0_sm *sm)
Definition: sm.c:1021
void m0_free(void *data)
Definition: memory.c:146
struct m0_rpc_item f_item
Definition: fop.h:83
M0_INTERNAL void m0_dtm0_tx_desc_fini(struct m0_dtm0_tx_desc *td)
Definition: tx_desc.c:111
struct m0_pdclust_src_addr src
Definition: fd.c:108
struct m0_reqh_service dos_generic
Definition: service.h:45
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
struct m0_fop_type dtm0_req_fop_fopt
Definition: fop.c:42
static void unlock(struct m0_long_lock *lock, struct m0_long_lock_link *link, bool check_ownership)
const m0_time_t M0_TIME_IMMEDIATELY
Definition: time.c:107
Definition: fop.h:79
M0_INTERNAL void m0_co_op_done(struct m0_co_op *op)
Definition: coroutine.c:218
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