Motr  M0
fop.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 
23 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_DTM0
24 #include "lib/trace.h" /* M0_LOG */
25 #include "cas/cas.h"
26 #include "cas/cas_xc.h"
27 #include "dtm0/fop.h"
28 #include "dtm0/fop_xc.h"
29 #include "dtm0/addb2.h"
30 #include "dtm0/drlink.h" /* m0_dtm0_req_post */
31 #include "dtm0/service.h" /* m0_dtm0_service */
32 #include "be/dtm0_log.h" /* m0_be_dtm0_log_* */
33 #include "be/queue.h" /* M0_BE_QUEUE_PUT */
34 #include "fop/fom_generic.h" /* M0_FOPH_* */
35 #include "lib/assert.h"
36 #include "lib/errno.h"
37 #include "lib/memory.h"
38 #include "lib/misc.h" /* M0_IN() */
39 #include "reqh/reqh.h" /* reqh::rh_beseg */
40 #include "rpc/rpc_opcodes.h" /* M0_DTM0_REP_OPCODE */
41 
45 
47 struct dtm0_fom {
48  struct m0_fom dtf_fom;
51 };
52 
53 static int dtm0_emsg_fom_tick(struct m0_fom *fom);
54 static int dtm0_pmsg_fom_tick(struct m0_fom *fom);
55 static int dtm0_rmsg_fom_tick(struct m0_fom *fom);
56 static int dtm0_tmsg_fom_tick(struct m0_fom *fom);
57 static int dtm0_fom_create(struct m0_fop *fop, struct m0_fom **out,
58  struct m0_reqh *reqh);
59 static void dtm0_fom_fini(struct m0_fom *fom);
60 static size_t dtm0_fom_locality(const struct m0_fom *fom);
61 static int dtm0_cas_fop_prepare(struct dtm0_req_fop *req,
62  struct m0_fop_type *cas_fopt,
63  struct m0_fop **cas_fop_out);
64 static int dtm0_cas_fom_spawn(
65  struct dtm0_fom *dfom,
66  struct m0_fop *cas_fop,
67  void (*on_cas_fom_complete)(struct m0_fom_thralldom *,
68  struct m0_fom *));
69 
70 static const struct m0_fom_ops dtm0_pmsg_fom_ops = {
72  .fo_tick = dtm0_pmsg_fom_tick,
73  .fo_home_locality = dtm0_fom_locality
74 };
75 
76 static const struct m0_fom_ops dtm0_rmsg_fom_ops = {
78  .fo_tick = dtm0_rmsg_fom_tick,
79  .fo_home_locality = dtm0_fom_locality
80 };
81 
82 static const struct m0_fom_ops dtm0_emsg_fom_ops = {
84  .fo_tick = dtm0_emsg_fom_tick,
85  .fo_home_locality = dtm0_fom_locality
86 };
87 
88 static const struct m0_fom_ops dtm0_tmsg_fom_ops = {
90  .fo_tick = dtm0_tmsg_fom_tick,
91  .fo_home_locality = dtm0_fom_locality
92 };
93 
95 
96 static const struct m0_fom_type_ops dtm0_req_fom_type_ops = {
98 };
99 
100 M0_INTERNAL void m0_dtm0_fop_fini(void)
101 {
108 }
109 
110 enum {
115 };
116 
118  [M0_FOPH_DTM0_ENTRY] = {
119  .sd_name = "dtm0-entry",
120  .sd_allowed = M0_BITS(M0_FOPH_DTM0_LOGGING,
124  },
126  .sd_name = "logging",
127  .sd_allowed = M0_BITS(M0_FOPH_SUCCESS,
129  },
130  [M0_FOPH_DTM0_TO_CAS] = {
131  .sd_name = "dtm0-to-cas",
132  .sd_allowed = M0_BITS(M0_FOPH_DTM0_CAS_DONE,
134  },
136  .sd_name = "cas-done",
137  .sd_allowed = M0_BITS(M0_FOPH_SUCCESS,
139  },
140 };
141 
144  {"dtm0-entry-fail", M0_FOPH_DTM0_ENTRY, M0_FOPH_FAILURE},
145  {"dtm0-entry-success", M0_FOPH_DTM0_ENTRY, M0_FOPH_SUCCESS},
146 
147  {"dtm0-logging", M0_FOPH_DTM0_ENTRY, M0_FOPH_DTM0_LOGGING},
148  {"dtm0-logging-fail", M0_FOPH_DTM0_LOGGING, M0_FOPH_FAILURE},
149  {"dtm0-logging-success", M0_FOPH_DTM0_LOGGING, M0_FOPH_SUCCESS},
150 
151  {"dtm0-to-cas", M0_FOPH_DTM0_ENTRY, M0_FOPH_DTM0_TO_CAS},
152 
153  {"dtm0-to-cas-fail", M0_FOPH_DTM0_TO_CAS, M0_FOPH_FAILURE},
154  {"dtm0-cas-done", M0_FOPH_DTM0_TO_CAS, M0_FOPH_DTM0_CAS_DONE},
155 
156  {"dtm0-cas-success", M0_FOPH_DTM0_CAS_DONE, M0_FOPH_SUCCESS},
157  {"dtm0-cas-fail", M0_FOPH_DTM0_CAS_DONE, M0_FOPH_FAILURE},
158 };
159 
160 static struct m0_sm_conf dtm0_conf = {
161  .scf_name = "dtm0-fom",
162  .scf_nr_states = ARRAY_SIZE(dtm0_phases),
163  .scf_state = dtm0_phases,
164  .scf_trans_nr = ARRAY_SIZE(dtm0_phases_trans),
165  .scf_trans = dtm0_phases_trans,
166 };
167 
168 M0_INTERNAL int m0_dtm0_fop_init(void)
169 {
170  static int init_once = 0;
171 
172  if (init_once++ > 0)
173  return 0;
174 
179 
180 
183  .name = "DTM0 request",
185  .xt = dtm0_req_fop_xc,
186  .rpc_flags = M0_RPC_MUTABO_REQ,
187  .fom_ops = &dtm0_req_fom_type_ops,
188  .sm = &dtm0_conf,
189  .svc_type = &dtm0_service_type);
191  .name = "DTM0 redo",
193  .xt = dtm0_req_fop_xc,
194  .rpc_flags = M0_RPC_ITEM_TYPE_REQUEST,
195  .fom_ops = &dtm0_req_fom_type_ops,
196  .sm = &dtm0_conf,
197  .svc_type = &dtm0_service_type);
199  .name = "DTM0 reply",
201  .xt = dtm0_rep_fop_xc,
202  .rpc_flags = M0_RPC_ITEM_TYPE_REPLY,
203  .fom_ops = &dtm0_req_fom_type_ops);
204 
207 }
208 
209 
210 /*
211  Allocates a fom.
212  */
213 static int dtm0_fom_create(struct m0_fop *fop,
214  struct m0_fom **out,
215  struct m0_reqh *reqh)
216 {
217  struct dtm0_fom *fom;
218  struct m0_fop *repfop;
219  struct dtm0_rep_fop *reply;
220  struct dtm0_req_fop *req;
221  struct m0_dtm0_pmsg_ast *pma;
222  int rc;
223 
224  M0_ENTRY("reqh=%p", reqh);
225 
226  M0_ALLOC_PTR(fom);
227  M0_ALLOC_PTR(pma);
229 
230  if (fom == NULL || repfop == NULL || pma == NULL) {
231  m0_free(pma);
232  m0_free(repfop);
233  m0_free(fom);
234  return M0_ERR(-ENOMEM);
235  }
236 
237  *out = &fom->dtf_fom;
238 
239  /* TODO: calculate credits for the operation. */
240 
241  /* see ::m0_dtm0_dtx_post_persistent for the details */
242  fop->f_opaque = pma;
243  reply = m0_fop_data(repfop);
244  req = m0_fop_data(fop);
245  reply->dr_txr = (struct m0_dtm0_tx_desc) {};
246  reply->dr_rc = 0;
247 
248  /* TODO avoid copy-paste */
249  if (req->dtr_msg == DTM_EXECUTE) {
250  M0_ASSERT_INFO(m0_dtm0_in_ut(), "Emsg FOM is only for UTs.");
251  rc = m0_dtm0_tx_desc_copy(&req->dtr_txr, &reply->dr_txr);
252  M0_ASSERT(rc == 0);
253  m0_fom_init(&fom->dtf_fom, &fop->f_type->ft_fom_type,
254  &dtm0_emsg_fom_ops, fop, repfop, reqh);
255  } else if (req->dtr_msg == DTM_PERSISTENT) {
256  m0_fom_init(&fom->dtf_fom, &fop->f_type->ft_fom_type,
257  &dtm0_pmsg_fom_ops, fop, repfop, reqh);
258  } else if (req->dtr_msg == DTM_REDO) {
259  m0_fom_init(&fom->dtf_fom, &fop->f_type->ft_fom_type,
260  &dtm0_rmsg_fom_ops, fop, repfop, reqh);
261  } else if (req->dtr_msg == DTM_TEST) {
262  m0_fom_init(&fom->dtf_fom, &fop->f_type->ft_fom_type,
263  &dtm0_tmsg_fom_ops, fop, repfop, reqh);
264  } else
265  M0_IMPOSSIBLE();
266 
267  return M0_RC_INFO(0, "fom=%p", &fom->dtf_fom);
268 }
269 
270 static void dtm0_fom_fini(struct m0_fom *fom)
271 {
272  M0_PRE(fom != NULL);
273 
274  m0_fom_fini(fom);
275  m0_free(fom);
276 }
277 
278 static size_t dtm0_fom_locality(const struct m0_fom *fom)
279 {
280  static size_t locality = 0;
281 
282  M0_PRE(fom != NULL);
283  return locality++;
284 }
285 
286 M0_INTERNAL int m0_dtm0_logrec_update(struct m0_be_dtm0_log *log,
287  struct m0_be_tx *tx,
288  struct m0_dtm0_tx_desc *txd,
289  struct m0_buf *payload)
290 {
291  int rc;
292 
293  M0_ENTRY();
294 
295  m0_mutex_lock(&log->dl_lock);
296  rc = m0_be_dtm0_log_update(log, tx, txd, payload);
297  m0_mutex_unlock(&log->dl_lock);
298 
299  return M0_RC(rc);
300 }
301 
302 M0_INTERNAL int m0_dtm0_on_committed(struct m0_fom *fom,
303  const struct m0_dtm0_tid *id)
304 {
305  struct m0_dtm0_service *dtms;
306  struct m0_be_dtm0_log *log;
307  const struct m0_dtm0_log_rec *rec;
308  const struct m0_fid *target;
309  const struct m0_fid *source;
310  struct dtm0_req_fop req = { .dtr_msg = DTM_PERSISTENT };
311  struct m0_dtm0_tx_desc *txd = &req.dtr_txr;
312  int rc;
313  int i;
314 
315  dtms = m0_dtm0_service_find(fom->fo_service->rs_reqh);
316 
317  /*
318  * It is impossible to commit a transaction without DTM0 service up and
319  * running.
320  */
321  M0_PRE(dtms != NULL);
322  log = dtms->dos_log;
323  M0_PRE(log != NULL);
324  /* It is impossible to commit something on a volatile log. */
325  M0_PRE(log->dl_is_persistent);
326 
327  M0_ENTRY();
328 
329  m0_mutex_lock(&log->dl_lock);
330  /* Get the latest state of the log record. */
331  rec = m0_be_dtm0_log_find(log, id);
332  /*
333  * It is impossible to commit a record that is not a part of the
334  * DTM log.
335  */
336  M0_ASSERT_INFO(rec != NULL, "Log record must be inserted into the log "
337  "in cas_fom_tick().");
338  rc = m0_dtm0_tx_desc_copy(&rec->dlr_txd, txd);
339  m0_mutex_unlock(&log->dl_lock);
340 
341  if (rc != 0)
342  goto out;
343 
344  /*
345  * We have to send N PERSISTENT messages once a local transaction
346  * gets committed (where N == txd->dtd_ps.dtp_nr):
347  * N-1 to the other participants (except ourselves),
348  * 1 to the originator (txd->dtd_id.dti_fid).
349  */
351  for (i = 0; i < txd->dtd_ps.dtp_nr; ++i) {
352  target = &txd->dtd_ps.dtp_pa[i].p_fid;
353 
354  /*
355  * Since we should not send Pmsg to ourselves, re-use this
356  * iteration to send Pmsg to the originator.
357  */
358  if (m0_fid_eq(target, source))
359  target = &txd->dtd_id.dti_fid;
360 
361  rc = m0_dtm0_req_post(dtms, NULL, &req, target, fom, false);
362  if (rc != 0) {
363  M0_LOG(M0_WARN, "Failed to send PERSISTENT msg "
364  FID_F " -> " FID_F " (%d).",
365  FID_P(source), FID_P(target), rc);
366  /*
367  * If we have failed to send a Pmsg (for any reason),
368  * it is still not a showstopper for the caller
369  * because the transaction has already been committed.
370  */
371  rc = 0;
372  }
373  }
374 
376 
377 out:
378  return M0_RC(rc);
379 }
380 
381 /*
382  * A FOM tick to handle a DTM0 PERSISTENT message (Pmsg).
383  * A group of Pmsgs is sent whenever a local transaction gets committed
384  * (see ::m0_dtm0_on_committed). This routine is the recipient of such
385  * messages.
386  */
387 static int dtm0_pmsg_fom_tick(struct m0_fom *fom)
388 {
389  int result = M0_FSO_AGAIN;
390  struct m0_dtm0_service *svc;
391  struct m0_buf buf = {};
392  struct dtm0_rep_fop *rep;
393  struct dtm0_req_fop *req = m0_fop_data(fom->fo_fop);
394  int phase = m0_fom_phase(fom);
395  struct m0_be_tx_credit cred = {};
396 
397  M0_PRE(req->dtr_msg == DTM_PERSISTENT);
398  M0_ENTRY("fom %p phase %d", fom, phase);
399 
400  switch (phase) {
401  case M0_FOPH_INIT ... M0_FOPH_NR - 1:
402  result = m0_fom_tick_generic(fom);
403  if (m0_dtm0_is_a_persistent_dtm(fom->fo_service) &&
405  M0_ASSERT(phase == M0_FOPH_TXN_INIT);
407  &req->dtr_txr, &buf,
408  m0_fom_reqh(fom)->rh_beseg,
409  NULL, &cred);
410  m0_be_tx_credit_add(&fom->fo_tx.tx_betx_cred, &cred);
411  }
412  break;
413 
414  case M0_FOPH_DTM0_ENTRY:
416  break;
417 
419  rep = m0_fop_data(fom->fo_rep_fop);
421  M0_ASSERT(svc != NULL);
422 
423  M0_LOG(M0_DEBUG, "Logging a P msg in phase %" PRIu32
424  " %d, " FID_F ", %p", req->dtr_msg,
425  !!m0_dtm0_is_a_volatile_dtm(fom->fo_service),
426  FID_P(&fom->fo_service->rs_service_fid),
427  fom->fo_service->rs_reqh);
428 
429  if (m0_dtm0_is_a_volatile_dtm(fom->fo_service)) {
430  /*
431  * On the client side, DTX is the owner of the
432  * corresponding log record, so that it cannot be
433  * modifed right here. We have to post an AST
434  * to ensure DTX is modifed under the group lock held.
435  */
436  m0_dtm0_dtx_pmsg_post(svc->dos_log, fom->fo_fop);
437  rep->dr_rc = 0;
438  } else {
439  rep->dr_rc = m0_dtm0_logrec_update(svc->dos_log,
440  &fom->fo_tx.tx_betx,
441  &req->dtr_txr, &buf);
442  }
443 
444  /* We do not handle any failures of Pmsg processing. */
446 
447  break;
448  default:
449  M0_IMPOSSIBLE("Invalid phase");
450  }
451 
452  return M0_RC(result);
453 }
454 
455 /*
456  * A FOM tick to handle a DTM0 EXECUTE message (Emsg).
457  * TODO:
458  * EXECUTE/EXECUTED message is "under development", and it is not a part
459  * of the main DTM0 algorithm yet.
460  * Previously, it was used to send ping-pongs in the UT. Once DTM0 RPC link
461  * gets its version of m0_rpc_post_sync, this FOM tick will be used in the
462  * UT that sends ping-pongs between volatile and persistent DTM0 services.
463  */
464 static int dtm0_emsg_fom_tick(struct m0_fom *fom)
465 {
466  int result = M0_FSO_AGAIN;
467  struct dtm0_rep_fop *rep = m0_fop_data(fom->fo_rep_fop);
468  struct dtm0_req_fop *req = m0_fop_data(fom->fo_fop);
469  int phase = m0_fom_phase(fom);
471  const struct m0_fid *tgt = &req->dtr_txr.dtd_id.dti_fid;
472  const struct dtm0_req_fop executed = {
473  .dtr_msg = DTM_EXECUTED,
474  .dtr_txr = req->dtr_txr,
475  };
476 
477  M0_PRE(req->dtr_msg == DTM_EXECUTE);
478  M0_ASSERT_INFO(m0_dtm0_in_ut(), "Emsg cannot be used outside of UT.");
479 
480  M0_ENTRY("fom %p phase %d", fom, phase);
481 
482  switch (phase) {
483  case M0_FOPH_INIT ... M0_FOPH_NR - 1:
484  result = m0_fom_tick_generic(fom);
485  break;
486  case M0_FOPH_DTM0_ENTRY:
487  if (m0_dtm0_is_a_persistent_dtm(fom->fo_service))
488  rep->dr_rc = m0_dtm0_req_post(svc, NULL, &executed,
489  tgt, fom, false);
491  break;
492  default:
493  M0_IMPOSSIBLE("Invalid phase");
494  }
495 
496  return M0_RC(result);
497 }
498 
500  struct m0_fom *serf)
501 {
502  struct dtm0_fom *leader = M0_AMB(leader, thrall, dtf_thrall);
503  struct m0_cas_rep *rep;
504  int rc;
505 
506  rc = m0_fom_rc(serf);
507  if (rc == 0) {
508  M0_ASSERT(serf->fo_rep_fop != NULL);
509  rep = (struct m0_cas_rep *)m0_fop_data(serf->fo_rep_fop);
510  M0_ASSERT(rep != NULL);
511  rc = rep->cgr_rc;
512  if (rc == 0) {
513  M0_ASSERT(rep->cgr_rep.cr_nr == 1);
514  rc = rep->cgr_rep.cr_rec[0].cr_rc;
515  }
516  }
517  leader->dtf_thrall_rc = rc;
518 }
519 
521  struct dtm0_fom *dfom,
522  struct m0_fop *cas_fop,
523  void (*on_cas_fom_complete)(struct m0_fom_thralldom *,
524  struct m0_fom *))
525 {
526 #ifndef __KERNEL__
527  return m0_cas_fom_spawn(&dfom->dtf_fom, &dfom->dtf_thrall,
528  cas_fop, on_cas_fom_complete);
529 #else
530  /* CAS service is not compiled for kernel. */
531  return 0;
532 #endif
533 }
534 
536  struct m0_fop_type *cas_fopt,
537  struct m0_fop **cas_fop_out)
538 {
539  int rc;
540  struct m0_cas_op *cas_op;
541  struct m0_fop *cas_fop;
542 
543  *cas_fop_out = NULL;
544 
546  M0_ALLOC_PTR(cas_fop);
547 
548  if (cas_op == NULL || cas_fop == NULL) {
549  rc = -ENOMEM;
550  } else {
553  req->dtr_payload.b_addr,
554  req->dtr_payload.b_nob);
555  if (rc == 0)
556  m0_fop_init(cas_fop, cas_fopt, cas_op, &m0_fop_release);
557  else
558  M0_LOG(M0_ERROR, "Could not decode the REDO payload");
559  }
560 
561  if (rc == 0) {
562  *cas_fop_out = cas_fop;
563  } else {
564  m0_free(cas_op);
565  m0_free(cas_fop);
566  }
567 
568  return rc;
569 }
570 
571 static int dtm0_rmsg_fom_tick(struct m0_fom *fom)
572 {
573  int rc;
574  int result = M0_FSO_AGAIN;
575  int phase = m0_fom_phase(fom);
576  struct dtm0_fom *dfom = M0_AMB(dfom, fom, dtf_fom);
577  struct dtm0_req_fop *req = m0_fop_data(fom->fo_fop);
578  struct m0_fop *cas_fop = NULL;
579 
580  M0_ENTRY("fom %p phase %d", fom, phase);
581 
582  switch (phase) {
583  case M0_FOPH_INIT ... M0_FOPH_NR - 1:
584  result = m0_fom_tick_generic(fom);
585  break;
586  case M0_FOPH_DTM0_ENTRY:
588  break;
589  case M0_FOPH_DTM0_TO_CAS:
590  /* REDO_END()s from all recovering processes received, send
591  * RECOVERED() message to the counterpart.
592 
593  cs_ha_process_event(m0_cs_ctx_get(m0_fom_reqh(fom)),
594  M0_CONF_HA_PROCESS_DTM_RECOVERED);
595  */
596  rc = dtm0_cas_fop_prepare(req, &cas_put_fopt, &cas_fop);
597  if (rc == 0) {
598  rc = dtm0_cas_fom_spawn(dfom, cas_fop,
600  if (rc != 0) {
601  M0_LOG(M0_ERROR, "Could not spawn CAS fom");
602  m0_fop_fini(cas_fop);
603  m0_free(cas_fop);
604  } else {
605  result = M0_FSO_WAIT;
606  }
607  } else {
608  M0_LOG(M0_ERROR, "Could not prepare CAS fop");
609  }
610 
611  if (rc != 0)
613  else
615  break;
617  if (dfom->dtf_thrall_rc != 0) {
618  M0_LOG(M0_ERROR, "Spawned CAS fom failed, rc = %d",
619  dfom->dtf_thrall_rc);
622  } else {
624  }
625  break;
626  default:
627  M0_IMPOSSIBLE("Invalid phase");
628  }
629  return M0_RC(result);
630 }
631 
633 static int dtm0_tmsg_fom_tick(struct m0_fom *fom)
634 {
636  struct dtm0_req_fop *req = m0_fop_data(fom->fo_fop);
637  int phase = m0_fom_phase(fom);
638  int result;
639 
640  M0_ENTRY("fom %p phase %d", fom, phase);
641 
642  if (m0_fom_phase(fom) < M0_FOPH_NR) {
643  result = m0_fom_tick_generic(fom);
644  } else {
645  m0_be_queue_lock(svc->dos_ut_queue);
647  M0_BE_QUEUE_PUT(svc->dos_ut_queue, &op,
648  &req->dtr_txr.dtd_id.dti_fid));
649  m0_be_queue_unlock(svc->dos_ut_queue);
651  result = M0_RC(M0_FSO_AGAIN);
652  }
653  return M0_RC(result);
654 }
655 
656 /*
657  * Local variables:
658  * c-indentation-style: "K&R"
659  * c-basic-offset: 8
660  * tab-width: 8
661  * fill-column: 80
662  * scroll-step: 1
663  * End:
664  */
M0_INTERNAL bool m0_dtm0_is_a_volatile_dtm(struct m0_reqh_service *service)
Definition: service.c:392
#define M0_PRE(cond)
M0_INTERNAL void m0_sm_conf_init(struct m0_sm_conf *conf)
Definition: sm.c:340
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
#define M0_BE_QUEUE_PUT(bq, op, ptr)
Definition: queue.h:236
M0_INTERNAL void m0_xc_dtm0_fop_init(void)
Definition: fop_xc.c:166
struct m0_xcode_type * dtm0_req_fop_xc
Definition: fop_xc.c:10
static const struct m0_fom_ops dtm0_pmsg_fom_ops
Definition: fop.c:70
#define NULL
Definition: misc.h:38
M0_INTERNAL struct m0_dtm0_service * m0_dtm0_service_find(const struct m0_reqh *reqh)
Definition: service.c:405
Definition: fop.h:50
static size_t locality(const struct m0_fom *fom)
Definition: rm_foms.c:269
static void init_once(void *foo)
Definition: inode.c:90
static struct m0_sm_conf dtm0_conf
Definition: fop.c:160
#define M0_FOP_TYPE_INIT(ft,...)
Definition: fop.h:308
Definition: sm.h:350
static struct io_request req
Definition: file.c:100
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:78
struct m0_reqh_service_type dtm0_service_type
Definition: service.c:60
#define M0_LOG(level,...)
Definition: trace.h:167
M0_INTERNAL void m0_xc_dtm0_fop_fini(void)
Definition: fop_xc.c:172
void m0_fop_type_addb2_deinstrument(struct m0_fop_type *type)
Definition: fop.c:492
static const struct m0_fom_ops dtm0_tmsg_fom_ops
Definition: fop.c:88
int(* fto_create)(struct m0_fop *fop, struct m0_fom **out, struct m0_reqh *reqh)
Definition: fom.h:650
struct m0_dtm0_tx_desc dlr_txd
Definition: dtm0_log.h:162
#define M0_BE_OP_SYNC(op_obj, action)
Definition: op.h:190
struct m0_xcode_type * dtm0_rep_fop_xc
Definition: fop_xc.c:11
struct m0_sm_trans_descr dtm0_phases_trans[]
Definition: fop.c:142
void * m0_fop_data(const struct m0_fop *fop)
Definition: fop.c:219
void m0_fop_type_fini(struct m0_fop_type *fopt)
Definition: fop.c:231
M0_INTERNAL void m0_sm_conf_trans_extend(const struct m0_sm_conf *base, struct m0_sm_conf *sub)
Definition: sm.c:726
M0_INTERNAL void m0_sm_conf_extend(const struct m0_sm_state_descr *base, struct m0_sm_state_descr *sub, uint32_t nr)
Definition: sm.c:763
#define M0_BITS(...)
Definition: misc.h:236
static int dtm0_rmsg_fom_tick(struct m0_fom *fom)
Definition: fop.c:571
static const struct m0_fom_ops dtm0_emsg_fom_ops
Definition: fop.c:82
M0_INTERNAL int m0_cas_fom_spawn(struct m0_fom *lead, struct m0_fom_thralldom *thrall, struct m0_fop *cas_fop, void(*on_fom_complete)(struct m0_fom_thralldom *, struct m0_fom *))
Definition: service.c:2578
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
static struct m0_xcode_type ** xt[]
Definition: protocol.c:64
const struct m0_sm_conf m0_generic_conf
Definition: fom_generic.c:838
struct m0_fop_getxattr_rep * rep
Definition: dir.c:455
m0_fom_phase
Definition: fom.h:372
Definition: sock.c:887
M0_INTERNAL int m0_dtm0_on_committed(struct m0_fom *fom, const struct m0_dtm0_tid *id)
Definition: fop.c:302
struct m0_fom_type ft_fom_type
Definition: fop.h:233
return M0_RC(rc)
struct m0_be_dtm0_log * dos_log
Definition: service.h:50
M0_INTERNAL void m0_dtm0_dtx_pmsg_post(struct m0_be_dtm0_log *log, struct m0_fop *fop)
Definition: dtx.c:381
op
Definition: libdemo.c:64
struct m0_dtm0_tid dtd_id
Definition: tx_desc.h:121
#define M0_ENTRY(...)
Definition: trace.h:170
M0_INTERNAL bool m0_dtm0_is_a_persistent_dtm(struct m0_reqh_service *service)
Definition: service.c:398
Definition: buf.h:37
M0_INTERNAL int m0_dtm0_fop_init(void)
Definition: fop.c:168
int opcode
Definition: crate.c:301
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
int i
Definition: dir.c:1033
#define M0_RC_INFO(rc, fmt,...)
Definition: trace.h:209
struct m0_fop_type * f_type
Definition: fop.h:82
static void dtm0_cas_done_cb(struct m0_fom_thralldom *thrall, struct m0_fom *serf)
Definition: fop.c:499
return M0_ERR(-EOPNOTSUPP)
Definition: fop.c:47
M0_INTERNAL void m0_be_queue_unlock(struct m0_be_queue *bq)
Definition: stubs.c:325
const char * name
Definition: trace.c:110
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
struct m0_fom_thralldom thrall
Definition: ms_fom_ut.c:110
struct m0_fom dtf_fom
Definition: fop.c:48
int m0_fom_tick_generic(struct m0_fom *fom)
Definition: fom_generic.c:848
void m0_fom_fini(struct m0_fom *fom)
Definition: fom.c:1324
#define M0_ASSERT(cond)
const char * scf_name
Definition: sm.h:352
void m0_fom_phase_move(struct m0_fom *fom, int32_t rc, int phase)
Definition: fom.c:1699
struct m0_fid rs_service_fid
Definition: reqh_service.h:221
uint32_t scf_nr_states
Definition: sm.h:354
M0_INTERNAL void m0_be_tx_credit_add(struct m0_be_tx_credit *c0, const struct m0_be_tx_credit *c1)
Definition: tx_credit.c:44
struct m0_xcode_type * m0_cas_op_xc
Definition: cas_xc.c:17
static const struct m0_fom_type_ops dtm0_req_fom_type_ops
Definition: fop.c:96
void * f_opaque
Definition: fop.h:85
Definition: reqh.h:94
Definition: dump.c:103
M0_INTERNAL void m0_dtm0_fop_fini(void)
Definition: fop.c:100
M0_INTERNAL void m0_fop_fini(struct m0_fop *fop)
Definition: fop.c:135
struct m0_fid p_fid
Definition: tx_desc.h:110
struct m0_fop_type dtm0_redo_fop_fopt
Definition: fop.c:44
#define FID_P(f)
Definition: fid.h:77
int dtf_thrall_rc
Definition: fop.c:50
Definition: cas.h:376
static void dtm0_fom_fini(struct m0_fom *fom)
Definition: fop.c:270
static int dtm0_fom_create(struct m0_fop *fop, struct m0_fom **out, struct m0_reqh *reqh)
Definition: fop.c:213
static const struct m0_fom_ops dtm0_rmsg_fom_ops
Definition: fop.c:76
struct m0_fop * m0_fop_reply_alloc(struct m0_fop *req, struct m0_fop_type *rept)
Definition: fop.c:128
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
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:75
Definition: fom.h:481
#define PRIu32
Definition: types.h:66
struct m0_dtm0_tx_pa * dtp_pa
Definition: tx_desc.h:117
struct m0_pdclust_tgt_addr tgt
Definition: fd.c:110
Definition: fop.h:46
struct m0_reqh reqh
Definition: rm_foms.c:48
const char * sd_name
Definition: sm.h:383
struct m0_sm_state_descr dtm0_phases[]
Definition: fop.c:117
struct m0_sm_state_descr * scf_state
Definition: sm.h:356
static int dtm0_pmsg_fom_tick(struct m0_fom *fom)
Definition: fop.c:387
Definition: fid.h:38
M0_INTERNAL int m0_be_dtm0_log_update(struct m0_be_dtm0_log *log, struct m0_be_tx *tx, struct m0_dtm0_tx_desc *txd, struct m0_buf *payload)
Definition: dtm0_log.c:452
M0_INTERNAL void m0_fop_release(struct m0_ref *ref)
Definition: fop.c:147
static int dtm0_cas_fop_prepare(struct dtm0_req_fop *req, struct m0_fop_type *cas_fopt, struct m0_fop **cas_fop_out)
Definition: fop.c:535
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
M0_INTERNAL void m0_be_dtm0_log_credit(enum m0_be_dtm0_log_credit_op op, struct m0_dtm0_tx_desc *txd, struct m0_buf *payload, struct m0_be_seg *seg, struct m0_dtm0_log_rec *rec, struct m0_be_tx_credit *accum)
Definition: dtm0_log.c:202
struct m0_fid dti_fid
Definition: tx_desc.h:95
int m0_fop_type_addb2_instrument(struct m0_fop_type *type)
Definition: fop.c:460
M0_INTERNAL int m0_xcode_obj_dec_from_buf(struct m0_xcode_obj *obj, void *buf, m0_bcount_t len)
Definition: xcode.c:850
static struct m0_net_test_service svc
Definition: service.c:34
M0_INTERNAL int m0_fom_rc(const struct m0_fom *fom)
Definition: fom.c:1727
M0_INTERNAL struct m0_dtm0_service * m0_dtm0_fom2service(struct m0_fom *fom)
Definition: service.c:88
struct m0_sm_trans_descr m0_generic_phases_trans[]
Definition: fom_generic.c:765
static struct m0_fop * fop
Definition: item.c:57
M0_INTERNAL void m0_be_queue_lock(struct m0_be_queue *bq)
Definition: stubs.c:321
static int dtm0_emsg_fom_tick(struct m0_fom *fom)
Definition: fop.c:464
struct m0_dtm0_tx_participants dtd_ps
Definition: tx_desc.h:122
static int dtm0_tmsg_fom_tick(struct m0_fom *fom)
Definition: fop.c:633
static size_t dtm0_fom_locality(const struct m0_fom *fom)
Definition: fop.c:278
void(* fo_fini)(struct m0_fom *fom)
Definition: fom.h:657
struct m0_fop * fo_rep_fop
Definition: fom.h:492
#define M0_ASSERT_INFO(cond, fmt,...)
#define M0_XCODE_OBJ(type, ptr)
Definition: xcode.h:962
M0_INTERNAL struct m0_fop_type cas_put_fopt
Definition: cas.c:49
static struct m0_cas_op * cas_op(const struct m0_fom *fom)
Definition: service.c:1769
bool dl_is_persistent
Definition: dtm0_log.h:194
M0_INTERNAL struct m0_dtm0_log_rec * m0_be_dtm0_log_find(struct m0_be_dtm0_log *log, const struct m0_dtm0_tid *id)
Definition: dtm0_log.c:270
#define out(...)
Definition: gen.c:41
void m0_fom_phase_set(struct m0_fom *fom, int phase)
Definition: fom.c:1688
M0_INTERNAL int m0_dtm0_logrec_update(struct m0_be_dtm0_log *log, struct m0_be_tx *tx, struct m0_dtm0_tx_desc *txd, struct m0_buf *payload)
Definition: fop.c:286
static struct m0_dtm_oper_descr reply
Definition: transmit.c:94
struct m0_mutex dl_lock
Definition: dtm0_log.h:200
Definition: net.c:93
void m0_free(void *data)
Definition: memory.c:146
M0_INTERNAL void m0_dtm0_tx_desc_fini(struct m0_dtm0_tx_desc *td)
Definition: tx_desc.c:110
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 int dtm0_cas_fom_spawn(struct dtm0_fom *dfom, struct m0_fop *cas_fop, void(*on_cas_fom_complete)(struct m0_fom_thralldom *, struct m0_fom *))
Definition: fop.c:520
Definition: fop.h:80
struct m0_fom_thralldom dtf_thrall
Definition: fop.c:49
#define FID_F
Definition: fid.h:75
M0_INTERNAL struct m0_reqh * m0_fom_reqh(const struct m0_fom *fom)
Definition: fom.c:283
Definition: trace.h:478
const uint64_t payload[]
Definition: base.c:65
Definition: tx.h:280
M0_INTERNAL bool m0_dtm0_in_ut(void)
Definition: service.c:414
#define M0_IMPOSSIBLE(fmt,...)
struct m0_fop_type dtm0_rep_fop_fopt
Definition: fop.c:43