Motr  M0
dtx.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 
28 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_DTM0
29 #include "dtm0/dtx.h"
30 #include "lib/assert.h" /* M0_PRE */
31 #include "lib/memory.h" /* M0_ALLOC */
32 #include "lib/errno.h" /* ENOMEM */
33 #include "lib/trace.h" /* M0_ERR */
34 #include "be/dtm0_log.h" /* dtm0_log API */
35 #include "conf/helpers.h" /* proc2srv */
36 #include "reqh/reqh.h" /* reqh2confc */
37 #include "rpc/rpc_machine.h" /* rpc_machine */
38 #include "dtm0/fop.h" /* dtm0 req fop */
39 #include "dtm0/service.h" /* m0_dtm0_service */
40 
41 static struct m0_sm_state_descr dtx_states[] = {
42  [M0_DDS_INIT] = {
44  .sd_name = "init",
45  .sd_allowed = M0_BITS(M0_DDS_INPROGRESS),
46  },
47  [M0_DDS_INPROGRESS] = {
48  .sd_name = "inprogress",
49  .sd_allowed = M0_BITS(M0_DDS_EXECUTED, M0_DDS_FAILED),
50  },
51  [M0_DDS_EXECUTED] = {
52  .sd_name = "executed",
53  .sd_allowed = M0_BITS(M0_DDS_EXECUTED_ALL),
54  },
56  .sd_name = "executed-all",
57  .sd_allowed = M0_BITS(M0_DDS_STABLE),
58  },
59  [M0_DDS_STABLE] = {
60  .sd_name = "stable",
61  .sd_allowed = M0_BITS(M0_DDS_DONE),
62  },
63  [M0_DDS_DONE] = {
64  .sd_name = "done",
65  .sd_flags = M0_SDF_TERMINAL,
66  },
67  [M0_DDS_FAILED] = {
68  .sd_name = "failed",
69  .sd_flags = M0_SDF_TERMINAL | M0_SDF_FAILURE
70  }
71 };
72 
73 static struct m0_sm_trans_descr dtx_trans[] = {
74  { "populated", M0_DDS_INIT, M0_DDS_INPROGRESS },
75  { "executed", M0_DDS_INPROGRESS, M0_DDS_EXECUTED },
76  { "exec-all", M0_DDS_EXECUTED, M0_DDS_EXECUTED_ALL },
77  { "exec-fail", M0_DDS_INPROGRESS, M0_DDS_FAILED },
78  { "stable", M0_DDS_EXECUTED_ALL, M0_DDS_STABLE },
79  { "prune", M0_DDS_STABLE, M0_DDS_DONE }
80 };
81 
83  .scf_name = "dtm0dtx",
84  .scf_nr_states = ARRAY_SIZE(dtx_states),
85  .scf_state = dtx_states,
86  .scf_trans_nr = ARRAY_SIZE(dtx_trans),
87  .scf_trans = dtx_trans,
88 };
89 
90 M0_INTERNAL void m0_dtm0_dtx_domain_init(void)
91 {
92  M0_ENTRY();
95  M0_LEAVE();
96 }
97 
98 M0_INTERNAL void m0_dtm0_dtx_domain_fini(void)
99 {
100  M0_ENTRY();
103  M0_LEAVE();
104 }
105 
106 static int dtx_log_insert(struct m0_dtm0_dtx *dtx)
107 {
108  struct m0_be_dtm0_log *log;
109  struct m0_dtm0_log_rec *record = M0_AMB(record, dtx, dlr_dtx);
110  int rc;
111 
113  M0_PRE(dtx->dd_dtms != NULL);
114  log = dtx->dd_dtms->dos_log;
115  M0_PRE(log != NULL);
116 
117  m0_mutex_lock(&log->dl_lock);
119  m0_mutex_unlock(&log->dl_lock);
120  return rc;
121 }
122 
123 static void dtx_log_update(struct m0_dtm0_dtx *dtx)
124 {
125  struct m0_be_dtm0_log *log;
126  struct m0_dtm0_log_rec *record = M0_AMB(record, dtx, dlr_dtx);
127 
128  M0_PRE(dtx->dd_dtms != NULL);
129  log = dtx->dd_dtms->dos_log;
130  M0_PRE(log != NULL);
131 
132  m0_mutex_lock(&log->dl_lock);
134  m0_mutex_unlock(&log->dl_lock);
135 }
136 
137 static void dtx_init(struct m0_dtm0_dtx *dtx,
138  struct m0_dtm0_service *svc,
139  struct m0_sm_group *grp)
140 {
141  dtx->dd_dtms = svc;
142  dtx->dd_ancient_dtx.tx_dtx = dtx;
145 }
146 
147 static struct m0_dtm0_dtx *dtx_alloc(struct m0_dtm0_service *svc,
148  struct m0_sm_group *grp)
149 {
150  struct m0_dtm0_log_rec *rec;
151 
152  M0_PRE(svc != NULL);
153  M0_PRE(grp != NULL);
154 
155  M0_ALLOC_PTR(rec);
156  if (rec == NULL)
157  return NULL;
158 
159  dtx_init(&rec->dlr_dtx, svc, grp);
160  return &rec->dlr_dtx;
161 }
162 
163 static void dtx_fini(struct m0_dtm0_dtx *dtx)
164 {
165  struct m0_dtm0_log_rec *rec;
166  M0_PRE(dtx != NULL);
167  rec = M0_AMB(rec, dtx, dlr_dtx);
169  rec->dlr_magic != 0),
170  "A DTX in INPROGRESS+ state must be a part of the log.");
171  m0_sm_fini(&dtx->dd_sm);
173  M0_SET0(dtx);
174 }
175 
176 static void dtx_prepare(struct m0_dtm0_dtx *dtx)
177 {
178  M0_ENTRY("dtx=%p", dtx);
179 
180  M0_PRE(dtx != NULL);
182  &dtx->dd_txd.dtd_id.dti_ts);
183 
186  M0_LEAVE("prepared dtx with tid "DTID0_F, DTID0_P(&dtx->dd_txd.dtd_id));
187 }
188 
189 static int dtx_open(struct m0_dtm0_dtx *dtx,
190  uint32_t nr_pa)
191 {
192  M0_PRE(dtx != NULL);
193  M0_ENTRY("dtx=%p", dtx);
194  return M0_RC(m0_dtm0_tx_desc_init(&dtx->dd_txd, nr_pa));
195 }
196 
197 static void dtx_fop_assign(struct m0_dtm0_dtx *dtx,
198  uint32_t pa_idx,
199  const struct m0_fop *pa_fop)
200 {
201  M0_PRE(dtx != NULL);
202  M0_PRE(pa_idx < dtx->dd_txd.dtd_ps.dtp_nr);
203 
204  M0_ENTRY("dtx=%p, pa=%" PRIu32 ", fop=%p", dtx, pa_idx, pa_fop);
205 
206  (void) pa_idx;
207 
208  /*
209  * TODO:REDO: On the DTM side we should enforce the requirement
210  * described at m0_dtm0_dtx::dd_op.
211  * At this moment we silently ignore this as well as anything
212  * related directly to REDO use-cases.
213  */
214  if (dtx->dd_fop == NULL) {
215  dtx->dd_fop = pa_fop;
216  }
217 
218  M0_LEAVE();
219 }
220 
221 
222 static int dtx_fid_assign(struct m0_dtm0_dtx *dtx,
223  uint32_t pa_idx,
224  const struct m0_fid *pa_sfid)
225 {
226  struct m0_dtm0_tx_pa *pa;
227  struct m0_reqh *reqh;
228  struct m0_conf_cache *cache;
229  struct m0_conf_obj *obj;
230  struct m0_conf_process *proc;
231  struct m0_fid rdtms_fid;
232  int rc;
233 
234  M0_ENTRY("dtx=%p", dtx);
235 
236  M0_PRE(dtx != NULL);
237  M0_PRE(pa_idx < dtx->dd_txd.dtd_ps.dtp_nr);
238  M0_PRE(m0_fid_is_valid(pa_sfid));
239 
240  /* XXX: Should we lock or release any conf objects or the cache? */
241 
244 
245  obj = m0_conf_cache_lookup(cache, pa_sfid);
246  if (obj == NULL)
247  return M0_ERR_INFO(-ENOENT,
248  "User service is not in the conf cache.");
249 
251  if (obj == NULL)
252  return M0_ERR_INFO(-ENOENT, "Process the service belongs to "
253  "is not a part of the conf cache.");
254 
256  M0_ASSERT_INFO(proc != NULL, "The grandparent is not a process?");
257 
259  &proc->pc_obj.co_id, M0_CST_DTM0,
260  &rdtms_fid);
261  if (rc != 0)
262  return M0_ERR_INFO(rc, "Cannot find remote DTM service on"
263  " the remote process that runs"
264  " this user service.");
265 
266  pa = &dtx->dd_txd.dtd_ps.dtp_pa[pa_idx];
267  M0_ASSERT_INFO(M0_IS0(pa), "FID cannot be re-assigned.");
268  M0_ASSERT(m0_fid_is_valid(&rdtms_fid));
269 
270  pa->p_fid = rdtms_fid;
271  M0_ASSERT(pa->p_state == M0_DTPS_INIT);
272  pa->p_state = M0_DTPS_INPROGRESS;
273 
274  return M0_RC_INFO(0, "pa %" PRIu32 ": "
275  FID_F " (User svc) => " FID_F " (DTM svc) ",
276  pa_idx, FID_P(pa_sfid), FID_P(&rdtms_fid));
277 }
278 
279 static int dtx_close(struct m0_dtm0_dtx *dtx)
280 {
281  int rc;
282 
283  M0_ENTRY("dtx=%p", dtx);
284 
285  M0_PRE(dtx != NULL);
287 
288  /*
289  * TODO:REDO: We may want to capture the fop contents here.
290  * See ::fol_record_pack and ::m0_fop_encdec for the details.
291  * At this moment we do not do REDO, so that it is safe to
292  * avoid any actions on the fop here.
293  */
294 
295  rc = dtx_log_insert(dtx);
296  M0_ASSERT(rc == 0);
297 
298  /*
299  * Once a dtx is closed, the FOP (or FOPs) has to be serialized
300  * into the log, so that we should no longer hold any references to it.
301  */
302  dtx->dd_fop = NULL;
304  return M0_RC(rc);
305 }
306 
307 static void dtx_done(struct m0_dtm0_dtx *dtx)
308 {
309  M0_ENTRY("dtx=%p", dtx);
310  M0_PRE(dtx != NULL);
314  dtx_fini(dtx);
315  M0_LEAVE();
316 }
317 
318 static void dtx_exec_all_ast_cb(struct m0_sm_group *grp, struct m0_sm_ast *ast)
319 {
320  struct m0_dtm0_dtx *dtx = ast->sa_datum;
321 
322  M0_ENTRY("dtx=%p", dtx);
323 
326 
329  M0_LOG(M0_DEBUG, "dtx " DTID0_F "is stable (EXEC_ALL)",
330  DTID0_P(&dtx->dd_txd.dtd_id));
331  }
332 
333  M0_LEAVE();
334 }
335 
337  struct m0_sm_ast *ast)
338 {
339  struct m0_dtm0_pmsg_ast *pma = ast->sa_datum;
340  struct m0_dtm0_dtx *dtx = pma->p_dtx;
341  struct m0_fop *fop = pma->p_fop;
342  struct dtm0_req_fop *req = m0_fop_data(fop);
343  const struct m0_dtm0_tx_desc *txd = &req->dtr_txr;
344 
345  M0_ENTRY("dtx=%p, fop=%p", dtx, fop);
346 
347  if (M0_IS0(dtx)) {
348  M0_LOG(M0_DEBUG, "Dtx has already reached DONE state, "
349  "ignoring P msg for " DTID0_F ".",
350  DTID0_P(&txd->dtd_id));
351  goto out;
352  }
353 
354  m0_dtm0_tx_desc_apply(&dtx->dd_txd, txd);
355  dtx_log_update(dtx);
356 
357  if (dtx->dd_sm.sm_state == M0_DDS_EXECUTED_ALL &&
360  M0_LOG(M0_DEBUG, "dtx " DTID0_F "is stable (PMA)",
361  DTID0_P(&dtx->dd_txd.dtd_id));
363  }
364 
365 out:
366  m0_free(pma);
367  m0_fop_put_lock(fop); /* it was taken in ::m0_dtm0_dtx_post_pmsg */
368  M0_LEAVE();
369 }
370 
371 M0_INTERNAL void m0_dtm0_dtx_pmsg_post(struct m0_dtm0_dtx *dtx,
372  struct m0_fop *fop)
373 {
374  struct m0_dtm0_pmsg_ast *pma;
375 
376  M0_PRE(fop != NULL);
377  M0_PRE(fop->f_opaque != NULL);
378  M0_PRE(m0_fop_data(fop) != NULL);
380 
381  M0_ENTRY("dtx=%p, fop=%p", dtx, fop);
382  /*
383  * XXX: it is an uncommon case where f_opaque is used on the server
384  * side (rather than on the client side) to associate a FOP with
385  * a user-defined datum. It helps to connect the lifetime of the
386  * AST that handles the notice with the lifetime of the FOP that
387  * has delivered the notice.
388  */
389  pma = fop->f_opaque;
390  M0_ASSERT_INFO(M0_IS0(pma), "PMA cannot be re-used");
391  *pma = (struct m0_dtm0_pmsg_ast) {
392  .p_dtx = dtx,
393  .p_fop = fop,
394  .p_ast = {
395  .sa_cb = dtx_persistent_ast_cb,
396  .sa_datum = pma,
397  },
398  };
399  m0_fop_get(fop); /* it will be put back by ::dtx_persistent_ast_cb */
400  m0_sm_ast_post(dtx->dd_sm.sm_grp, &pma->p_ast);
401  M0_LEAVE();
402 }
403 
404 static void dtx_executed(struct m0_dtm0_dtx *dtx, uint32_t idx)
405 {
406  struct m0_dtm0_tx_pa *pa;
407 
408  M0_ENTRY("dtx=%p, idx=%"PRIu32, dtx, idx);
409 
410  M0_PRE(dtx != NULL);
412 
413  pa = &dtx->dd_txd.dtd_ps.dtp_pa[idx];
414 
415  M0_ASSERT(pa->p_state >= M0_DTPS_INPROGRESS);
416 
417  pa->p_state = max_check(pa->p_state, (uint32_t)M0_DTPS_EXECUTED);
418 
419  dtx->dd_nr_executed++;
420 
421  if (dtx->dd_sm.sm_state < M0_DDS_EXECUTED) {
424  }
425 
426  if (dtx->dd_nr_executed == dtx->dd_txd.dtd_ps.dtp_nr) {
429  "Non-executed PAs should not exist "
430  "at this point.");
432 
433  /*
434  * EXECUTED and STABLE should not be triggered within the
435  * same ast tick. This ast helps us to enforce it.
436  * XXX: there is a catch22-like problem with DIX states:
437  * DIX request should already be in "FINAL" state when
438  * the corresponding dtx reaches STABLE. However, the dtx
439  * cannot transit from EXECUTED to STABLE (through EXEC_ALL)
440  * if DIX reached FINAL already (the list of CAS rops has been
441  * destroyed). So that the EXEC_ALL ast cuts this knot by
442  * scheduling the transition EXEC_ALL -> STABLE in a separate
443  * tick where DIX request reached FINAL.
444  */
445  dtx->dd_exec_all_ast = (struct m0_sm_ast) {
447  .sa_datum = dtx,
448  };
450  }
451 
452  dtx_log_update(dtx);
453  M0_LEAVE();
454 }
455 
456 M0_INTERNAL struct m0_dtx* m0_dtx0_alloc(struct m0_dtm0_service *svc,
457  struct m0_sm_group *grp)
458 {
459  struct m0_dtm0_dtx *dtx = dtx_alloc(svc, grp);
460  return dtx ? &dtx->dd_ancient_dtx : NULL;
461 }
462 
463 M0_INTERNAL void m0_dtx0_prepare(struct m0_dtx *dtx)
464 {
465  M0_PRE(dtx != NULL);
466  dtx_prepare(dtx->tx_dtx);
467 }
468 
469 M0_INTERNAL int m0_dtx0_open(struct m0_dtx *dtx, uint32_t nr)
470 {
471  M0_PRE(dtx != NULL);
472  return dtx_open(dtx->tx_dtx, nr);
473 }
474 
475 M0_INTERNAL int m0_dtx0_fid_assign(struct m0_dtx *dtx,
476  uint32_t pa_idx,
477  const struct m0_fid *pa_sfid)
478 {
479  M0_PRE(dtx != NULL);
480  return dtx_fid_assign(dtx->tx_dtx, pa_idx, pa_sfid);
481 }
482 
483 M0_INTERNAL void m0_dtx0_fop_assign(struct m0_dtx *dtx,
484  uint32_t pa_idx,
485  const struct m0_fop *pa_fop)
486 {
487  M0_PRE(dtx != NULL);
488  dtx_fop_assign(dtx->tx_dtx, pa_idx, pa_fop);
489 }
490 
491 
492 M0_INTERNAL int m0_dtx0_close(struct m0_dtx *dtx)
493 {
494  M0_PRE(dtx != NULL);
495  return dtx_close(dtx->tx_dtx);
496 }
497 
498 M0_INTERNAL void m0_dtx0_executed(struct m0_dtx *dtx, uint32_t pa_idx)
499 {
500  M0_PRE(dtx != NULL);
501  dtx_executed(dtx->tx_dtx, pa_idx);
502 }
503 
504 M0_INTERNAL void m0_dtx0_done(struct m0_dtx *dtx)
505 {
506  M0_PRE(dtx != NULL);
507  dtx_done(dtx->tx_dtx);
508 }
509 
510 M0_INTERNAL int m0_dtx0_txd_copy(const struct m0_dtx *dtx,
511  struct m0_dtm0_tx_desc *dst)
512 {
513  if (dtx == NULL) {
514  /* No DTX => no txr */
515  M0_SET0(dst);
516  return 0;
517  }
518 
519  return m0_dtm0_tx_desc_copy(&dtx->tx_dtx->dd_txd, dst);
520 }
521 
522 M0_INTERNAL enum m0_dtm0_dtx_state m0_dtx0_sm_state(const struct m0_dtx *dtx)
523 {
524  M0_PRE(dtx != NULL);
525  return dtx->tx_dtx->dd_sm.sm_state;
526 }
527 
528 #undef M0_TRACE_SUBSYSTEM
529 
532 /*
533  * Local variables:
534  * c-indentation-style: "K&R"
535  * c-basic-offset: 8
536  * tab-width: 8
537  * fill-column: 80
538  * scroll-step: 1
539  * End:
540  */
541 /*
542  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
543  */
static int dtx_close(struct m0_dtm0_dtx *dtx)
Definition: dtx.c:279
struct m0_fid co_id
Definition: obj.h:208
Definition: beck.c:235
M0_INTERNAL int m0_dtm0_tx_desc_init(struct m0_dtm0_tx_desc *td, uint32_t nr_pa)
Definition: tx_desc.c:97
static size_t nr
Definition: dump.c:1505
struct m0_dtm0_dtx * tx_dtx
Definition: dtm.h:563
#define M0_PRE(cond)
M0_INTERNAL void m0_sm_conf_init(struct m0_sm_conf *conf)
Definition: sm.c:340
Definition: dtm.h:554
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
struct m0_dtx dd_ancient_dtx
Definition: dtx.h:59
M0_INTERNAL int m0_dtx0_open(struct m0_dtx *dtx, uint32_t nr)
Definition: dtx.c:469
#define NULL
Definition: misc.h:38
static struct m0_dtm0_dtx * dtx_alloc(struct m0_dtm0_service *svc, struct m0_sm_group *grp)
Definition: dtx.c:147
static struct m0_bufvec dst
Definition: xform.c:61
struct m0_dtm0_dtx dlr_dtx
Definition: dtm0_log.h:161
struct m0_fop * p_fop
Definition: dtx.h:82
#define ergo(a, b)
Definition: misc.h:293
void(* sa_cb)(struct m0_sm_group *grp, struct m0_sm_ast *)
Definition: sm.h:506
static struct m0_sm_state_descr dtx_states[]
Definition: dtx.c:41
Definition: sm.h:350
M0_INTERNAL void m0_dtm0_dtx_pmsg_post(struct m0_dtm0_dtx *dtx, struct m0_fop *fop)
Definition: dtx.c:371
static struct io_request req
Definition: file.c:100
static struct m0_sm_group * grp
Definition: bytecount.c:38
M0_INTERNAL struct m0_conf_obj * m0_conf_cache_lookup(const struct m0_conf_cache *cache, const struct m0_fid *id)
Definition: cache.c:106
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
M0_INTERNAL void m0_sm_ast_post(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: sm.c:135
M0_INTERNAL void m0_dtx0_done(struct m0_dtx *dtx)
Definition: dtx.c:504
static void dtx_fini(struct m0_dtm0_dtx *dtx)
Definition: dtx.c:163
static struct m0_sm_trans_descr dtx_trans[]
Definition: dtx.c:73
#define max_check(a, b)
Definition: arith.h:95
M0_INTERNAL int m0_dtx0_txd_copy(const struct m0_dtx *dtx, struct m0_dtm0_tx_desc *dst)
Definition: dtx.c:510
M0_INTERNAL int m0_dtx0_close(struct m0_dtx *dtx)
Definition: dtx.c:492
struct m0_dtm0_ts dti_ts
Definition: tx_desc.h:94
void * m0_fop_data(const struct m0_fop *fop)
Definition: fop.c:220
M0_INTERNAL void m0_dtx0_prepare(struct m0_dtx *dtx)
Definition: dtx.c:463
M0_DTPS_INPROGRESS
Definition: tx_desc.h:164
#define M0_BITS(...)
Definition: misc.h:236
Definition: sm.h:504
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
M0_INTERNAL bool m0_sm_addb2_counter_init(struct m0_sm *sm)
Definition: sm.c:891
M0_INTERNAL void m0_be_dtm0_volatile_log_update(struct m0_be_dtm0_log *log, struct m0_dtm0_log_rec *rec)
Definition: dtm0_log.c:555
static struct foo * obj
Definition: tlist.c:302
struct m0_sm dd_sm
Definition: dtx.h:61
struct m0_sm_group rm_sm_grp
Definition: rpc_machine.h:82
struct m0_sm_ast p_ast
Definition: dtx.h:80
return M0_RC(rc)
struct m0_be_dtm0_log * dos_log
Definition: service.h:50
M0_INTERNAL void m0_dtm0_tx_desc_apply(struct m0_dtm0_tx_desc *tgt, const struct m0_dtm0_tx_desc *upd)
Definition: tx_desc.c:127
struct m0_dtm0_tid dtd_id
Definition: tx_desc.h:121
#define M0_ENTRY(...)
Definition: trace.h:170
static struct m0_sm_ast ast[NR]
Definition: locality.c:44
#define M0_RC_INFO(rc, fmt,...)
Definition: trace.h:209
M0_INTERNAL struct m0_dtx * m0_dtx0_alloc(struct m0_dtm0_service *svc, struct m0_sm_group *grp)
Definition: dtx.c:456
#define M0_ERR_INFO(rc, fmt,...)
Definition: trace.h:215
M0_INTERNAL void m0_dtm0_dtx_domain_init(void)
Definition: dtx.c:90
static int dtx_fid_assign(struct m0_dtm0_dtx *dtx, uint32_t pa_idx, const struct m0_fid *pa_sfid)
Definition: dtx.c:222
void * sa_datum
Definition: sm.h:508
M0_INTERNAL struct m0_confc * m0_reqh2confc(struct m0_reqh *reqh)
Definition: reqh.c:753
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
M0_INTERNAL int m0_be_dtm0_volatile_log_insert(struct m0_be_dtm0_log *log, struct m0_dtm0_log_rec *rec)
Definition: dtm0_log.c:540
static int dtx_log_insert(struct m0_dtm0_dtx *dtx)
Definition: dtx.c:106
#define M0_ASSERT(cond)
const char * scf_name
Definition: sm.h:352
m0_dtm0_dtx_state
Definition: dtx.h:31
M0_INTERNAL void m0_dtm0_clk_src_now(struct m0_dtm0_clk_src *cs, struct m0_dtm0_ts *now)
Definition: clk_src.c:71
static void dtx_exec_all_ast_cb(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: dtx.c:318
void m0_sm_state_set(struct m0_sm *mach, int state)
Definition: sm.c:478
struct m0_conf_obj * m0_conf_obj_grandparent(const struct m0_conf_obj *obj)
Definition: obj.c:384
struct m0_fid rs_service_fid
Definition: reqh_service.h:220
M0_INTERNAL bool m0_dtm0_tid__invariant(const struct m0_dtm0_tid *tid)
Definition: tx_desc.c:68
uint64_t dlr_magic
Definition: dtm0_log.h:163
struct m0_dtm0_clk_src dos_clk_src
Definition: service.h:49
struct m0_conf_cache cc_cache
Definition: confc.h:394
M0_INTERNAL void m0_dtm0_dtx_domain_fini(void)
Definition: dtx.c:98
M0_DTPS_EXECUTED
Definition: tx_desc.h:164
static void dtx_fop_assign(struct m0_dtm0_dtx *dtx, uint32_t pa_idx, const struct m0_fop *pa_fop)
Definition: dtx.c:197
struct m0_fop * m0_fop_get(struct m0_fop *fop)
Definition: fop.c:162
struct m0_sm_group * sm_grp
Definition: sm.h:321
static void dtx_executed(struct m0_dtm0_dtx *dtx, uint32_t idx)
Definition: dtx.c:404
void * f_opaque
Definition: fop.h:84
#define M0_POST(cond)
Definition: reqh.h:94
struct m0_fid p_fid
Definition: tx_desc.h:110
#define M0_CONF_CAST(ptr, type)
Definition: obj.h:780
static void dtx_init(struct m0_dtm0_dtx *dtx, struct m0_dtm0_service *svc, struct m0_sm_group *grp)
Definition: dtx.c:137
#define FID_P(f)
Definition: fid.h:77
static int dtx_open(struct m0_dtm0_dtx *dtx, uint32_t nr_pa)
Definition: dtx.c:189
const struct m0_fop * dd_fop
Definition: dtx.h:74
uint32_t sd_flags
Definition: sm.h:378
M0_INTERNAL int m0_conf_process2service_get(struct m0_confc *confc, const struct m0_fid *process_fid, enum m0_conf_service_type stype, struct m0_fid *sfid)
Definition: helpers.c:518
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
struct m0_conf_obj pc_obj
Definition: obj.h:581
#define PRIu32
Definition: types.h:66
struct m0_dtm0_tx_pa * dtp_pa
Definition: tx_desc.h:117
#define dtds_forall(__txd, __exp)
Definition: tx_desc.h:163
struct m0_reqh reqh
Definition: rm_foms.c:48
M0_INTERNAL void m0_dtx0_executed(struct m0_dtx *dtx, uint32_t pa_idx)
Definition: dtx.c:498
static void dtx_done(struct m0_dtm0_dtx *dtx)
Definition: dtx.c:307
M0_INTERNAL int m0_dtx0_fid_assign(struct m0_dtx *dtx, uint32_t pa_idx, const struct m0_fid *pa_sfid)
Definition: dtx.c:475
Definition: fid.h:38
struct m0_confc rc_confc
Definition: rconfc.h:235
M0_INTERNAL void m0_dtx0_fop_assign(struct m0_dtx *dtx, uint32_t pa_idx, const struct m0_fop *pa_fop)
Definition: dtx.c:483
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
struct m0_dtm0_service * dd_dtms
Definition: dtx.h:63
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
M0_DTPS_PERSISTENT
Definition: tx_desc.h:164
struct m0_dtm0_dtx * p_dtx
Definition: dtx.h:84
struct m0_fid dti_fid
Definition: tx_desc.h:95
static struct m0_net_test_service svc
Definition: service.c:34
M0_INTERNAL enum m0_dtm0_dtx_state m0_dtx0_sm_state(const struct m0_dtx *dtx)
Definition: dtx.c:522
void m0_fop_put_lock(struct m0_fop *fop)
Definition: fop.c:199
static struct m0_fop * fop
Definition: item.c:57
M0_INTERNAL bool m0_dtm0_tx_desc_state_eq(const struct m0_dtm0_tx_desc *txd, enum m0_dtm0_tx_pa_state state)
Definition: tx_desc.c:155
Definition: record.py:1
struct m0_dtm0_tx_participants dtd_ps
Definition: tx_desc.h:122
#define DTID0_P(__tid)
Definition: tx_desc.h:99
struct m0_rconfc rh_rconfc
Definition: reqh.h:166
#define M0_ASSERT_INFO(cond, fmt,...)
M0_DTPS_INIT
Definition: tx_desc.h:164
uint32_t dd_nr_executed
Definition: dtx.h:64
struct m0_sm_conf m0_dtx_sm_conf
Definition: dtx.c:82
#define out(...)
Definition: gen.c:41
struct m0_sm_ast dd_exec_all_ast
Definition: dtx.h:65
M0_INTERNAL void m0_sm_conf_fini(struct m0_sm_conf *conf)
Definition: sm.c:376
M0_INTERNAL bool m0_sm_conf_is_initialized(const struct m0_sm_conf *conf)
Definition: sm.c:382
M0_INTERNAL bool m0_fid_is_valid(const struct m0_fid *fid)
Definition: fid.c:96
#define DTID0_F
Definition: tx_desc.h:98
struct m0_rpc_machine * ri_rmachine
Definition: item.h:160
struct m0_mutex dl_lock
Definition: dtm0_log.h:198
struct m0_reqh * rs_reqh
Definition: reqh_service.h:259
void m0_free(void *data)
Definition: memory.c:146
struct m0_rpc_item f_item
Definition: fop.h:83
static void dtx_prepare(struct m0_dtm0_dtx *dtx)
Definition: dtx.c:176
uint32_t sm_state
Definition: sm.h:307
M0_INTERNAL void m0_dtm0_tx_desc_fini(struct m0_dtm0_tx_desc *td)
Definition: tx_desc.c:111
struct m0_reqh_service dos_generic
Definition: service.h:45
static void dtx_log_update(struct m0_dtm0_dtx *dtx)
Definition: dtx.c:123
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
M0_INTERNAL bool m0_sm_group_is_locked(const struct m0_sm_group *grp)
Definition: sm.c:107
Definition: fop.h:79
#define FID_F
Definition: fid.h:75
static void dtx_persistent_ast_cb(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: dtx.c:336
struct m0_dtm0_tx_desc dd_txd
Definition: dtx.h:62
M0_INTERNAL void m0_sm_fini(struct m0_sm *mach)
Definition: sm.c:331