Motr  M0
req.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 
30 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_DIX
31 #include "lib/trace.h"
32 #include "lib/memory.h"
33 #include "lib/buf.h"
34 #include "lib/vec.h"
35 #include "lib/finject.h"
36 #include "conf/schema.h" /* M0_CST_CAS */
37 #include "sm/sm.h"
38 #include "pool/pool.h" /* m0_pool_version_find */
39 #include "cas/client.h"
40 #include "cas/cas.h" /* m0_dix_fid_type */
41 #include "dix/layout.h"
42 #include "dix/meta.h"
43 #include "dix/req.h"
44 #include "dix/client.h"
45 #include "dix/client_internal.h" /* m0_dix_pver */
46 #include "dix/fid_convert.h"
47 #include "dix/dix_addb.h"
48 #include "dtm0/dtx.h" /* m0_dtx0_* API */
49 
50 static struct m0_sm_state_descr dix_req_states[] = {
51  [DIXREQ_INIT] = {
53  .sd_name = "init",
54  .sd_allowed = M0_BITS(DIXREQ_DISCOVERY_DONE,
58  },
60  .sd_name = "layout-discovery",
61  .sd_allowed = M0_BITS(DIXREQ_DISCOVERY_DONE,
65  },
67  .sd_name = "lid-discovery",
68  .sd_allowed = M0_BITS(DIXREQ_DISCOVERY_DONE,
71  },
73  .sd_name = "discovery-done",
74  .sd_allowed = M0_BITS(DIXREQ_INPROGRESS,
77  },
78  [DIXREQ_META_UPDATE] = {
79  .sd_name = "idxop-meta-update",
80  .sd_allowed = M0_BITS(DIXREQ_INPROGRESS, DIXREQ_FINAL,
82  },
83  [DIXREQ_INPROGRESS] = {
84  .sd_name = "in-progress",
85  .sd_allowed = M0_BITS(DIXREQ_GET_RESEND, DIXREQ_FINAL,
87  },
88  [DIXREQ_GET_RESEND] = {
89  .sd_name = "resend-get-req",
91  },
92  [DIXREQ_DEL_PHASE2] = {
93  .sd_name = "delete-phase2",
94  .sd_allowed = M0_BITS(DIXREQ_FINAL, DIXREQ_FAILURE)
95  },
96  [DIXREQ_FINAL] = {
97  .sd_name = "final",
98  .sd_flags = M0_SDF_TERMINAL,
99  },
100  [DIXREQ_FAILURE] = {
101  .sd_name = "failure",
102  .sd_flags = M0_SDF_TERMINAL | M0_SDF_FAILURE
103  }
104 };
105 
107 static struct m0_sm_trans_descr dix_req_trans[] = {
108  { "layouts-known", DIXREQ_INIT, DIXREQ_DISCOVERY_DONE },
109  { "find-layouts", DIXREQ_INIT, DIXREQ_LAYOUT_DISCOVERY },
110  { "resolve-lids", DIXREQ_INIT, DIXREQ_LID_DISCOVERY },
111  { "copy-fail", DIXREQ_INIT, DIXREQ_FAILURE },
112  { "layouts-found", DIXREQ_LAYOUT_DISCOVERY, DIXREQ_DISCOVERY_DONE },
114  { "not-found", DIXREQ_LAYOUT_DISCOVERY, DIXREQ_FAILURE },
115  { "desc-final", DIXREQ_LAYOUT_DISCOVERY, DIXREQ_FINAL },
116  { "lids-resolved", DIXREQ_LID_DISCOVERY, DIXREQ_DISCOVERY_DONE },
117  { "not-resolved", DIXREQ_LID_DISCOVERY, DIXREQ_FAILURE },
118  { "lid-final", DIXREQ_LID_DISCOVERY, DIXREQ_FINAL },
119  { "create/delete", DIXREQ_DISCOVERY_DONE, DIXREQ_META_UPDATE },
121  { "failure", DIXREQ_DISCOVERY_DONE, DIXREQ_FAILURE },
122  { "meta-updated", DIXREQ_META_UPDATE, DIXREQ_INPROGRESS },
123  { "crow-or-fail", DIXREQ_META_UPDATE, DIXREQ_FINAL },
124  { "update-fail", DIXREQ_META_UPDATE, DIXREQ_FAILURE },
125  { "get-req-fail", DIXREQ_INPROGRESS, DIXREQ_GET_RESEND },
126  { "rpc-failure", DIXREQ_INPROGRESS, DIXREQ_FAILURE },
127  { "req-processed", DIXREQ_INPROGRESS, DIXREQ_FINAL },
128  { "inp-del-ph2", DIXREQ_INPROGRESS, DIXREQ_DEL_PHASE2 },
129  { "del-ph2-final", DIXREQ_DEL_PHASE2, DIXREQ_FINAL },
130  { "del-ph2-fail", DIXREQ_DEL_PHASE2, DIXREQ_FAILURE },
131  { "all-cctg-fail", DIXREQ_GET_RESEND, DIXREQ_FAILURE },
132  { "resend", DIXREQ_GET_RESEND, DIXREQ_INPROGRESS },
133 };
134 
136  .scf_name = "dix_req",
137  .scf_nr_states = ARRAY_SIZE(dix_req_states),
138  .scf_state = dix_req_states,
139  .scf_trans_nr = ARRAY_SIZE(dix_req_trans),
140  .scf_trans = dix_req_trans
141 };
142 
143 M0_TL_DESCR_DEFINE(cas_rop, "cas record operations",
144  M0_INTERNAL, struct m0_dix_cas_rop, crp_linkage, crp_magix,
146 M0_TL_DEFINE(cas_rop, M0_INTERNAL, struct m0_dix_cas_rop);
147 
148 static void dix_idxop(struct m0_dix_req *req);
149 static void dix_rop(struct m0_dix_req *req);
150 static void dix_rop_units_set(struct m0_dix_req *req);
151 static int dix_cas_rops_alloc(struct m0_dix_req *req);
152 static int dix_cas_rops_fill(struct m0_dix_req *req);
153 static int dix_cas_rops_send(struct m0_dix_req *req);
154 static void dix_ldescr_resolve(struct m0_dix_req *req);
155 static void dix_discovery_completed(struct m0_dix_req *req);
156 static int dix_idxop_reqs_send(struct m0_dix_req *req);
157 static void dix_discovery(struct m0_dix_req *req);
158 
159 static int dix_id_layouts_nr(struct m0_dix_req *req);
160 static int dix_unknown_layouts_nr(struct m0_dix_req *req);
161 static uint32_t dix_rop_tgt_iter_max(struct m0_dix_req *req,
162  struct m0_dix_rec_op *rec_op);
163 
164 
165 static bool dix_req_is_idxop(const struct m0_dix_req *req)
166 {
167  return M0_IN(req->dr_type, (DIX_CREATE, DIX_DELETE, DIX_CCTGS_LOOKUP));
168 }
169 
170 static struct m0_sm_group *dix_req_smgrp(const struct m0_dix_req *req)
171 {
172  return req->dr_sm.sm_grp;
173 }
174 
175 static void dix_to_cas_map(const struct m0_dix_req *dreq,
176  const struct m0_cas_req *creq)
177 {
178  uint64_t did = m0_sm_id_get(&dreq->dr_sm);
179  uint64_t cid = m0_sm_id_get(&creq->ccr_sm);
180  M0_ADDB2_ADD(M0_AVI_DIX_TO_CAS, did, cid);
181 }
182 
183 
184 M0_INTERNAL void m0_dix_req_lock(struct m0_dix_req *req)
185 {
186  M0_ENTRY();
188 }
189 
190 M0_INTERNAL void m0_dix_req_unlock(struct m0_dix_req *req)
191 {
192  M0_ENTRY();
194 }
195 
196 M0_INTERNAL bool m0_dix_req_is_locked(const struct m0_dix_req *req)
197 {
199 }
200 
201 M0_INTERNAL int m0_dix_req_wait(struct m0_dix_req *req, uint64_t states,
202  m0_time_t to)
203 {
204  M0_ENTRY();
206  return M0_RC(m0_sm_timedwait(&req->dr_sm, states, to));
207 }
208 
209 static void dix_req_init(struct m0_dix_req *req,
210  struct m0_dix_cli *cli,
211  struct m0_sm_group *grp,
212  bool meta)
213 {
214  M0_SET0(req);
215  req->dr_cli = cli;
216  req->dr_is_meta = meta;
218  m0_sm_addb2_counter_init(&req->dr_sm);
219 }
220 
221 M0_INTERNAL void m0_dix_mreq_init(struct m0_dix_req *req,
222  struct m0_dix_cli *cli,
223  struct m0_sm_group *grp)
224 {
225  dix_req_init(req, cli, grp, true);
226 }
227 
228 M0_INTERNAL void m0_dix_req_init(struct m0_dix_req *req,
229  struct m0_dix_cli *cli,
230  struct m0_sm_group *grp)
231 {
232  dix_req_init(req, cli, grp, false);
233 }
234 
235 static enum m0_dix_req_state dix_req_state(const struct m0_dix_req *req)
236 {
237  return req->dr_sm.sm_state;
238 }
239 
240 static void dix_req_state_set(struct m0_dix_req *req,
241  enum m0_dix_req_state state)
242 {
243  M0_LOG(M0_DEBUG, "DIX req: %p, state change:[%s -> %s]\n",
244  req, m0_sm_state_name(&req->dr_sm, req->dr_sm.sm_state),
245  m0_sm_state_name(&req->dr_sm, state));
246  m0_sm_state_set(&req->dr_sm, state);
247 }
248 
249 static void dix_req_failure(struct m0_dix_req *req, int32_t rc)
250 {
251  M0_PRE(rc != 0);
252  m0_sm_fail(&req->dr_sm, DIXREQ_FAILURE, rc);
253 }
254 
255 static int dix_type_layouts_nr(struct m0_dix_req *req,
256  enum dix_layout_type type)
257 {
258  return m0_count(i, req->dr_indices_nr,
259  req->dr_indices[i].dd_layout.dl_type == type);
260 }
261 
262 static int dix_resolved_nr(struct m0_dix_req *req)
263 {
265 }
266 
267 static int dix_id_layouts_nr(struct m0_dix_req *req)
268 {
270 }
271 
273 {
275 }
276 
277 static void dix_to_mdix_map(const struct m0_dix_req *req,
278  const struct m0_dix_meta_req *mreq)
279 {
280  uint64_t rid = m0_sm_id_get(&req->dr_sm);
281  uint64_t mid = m0_sm_id_get(&mreq->dmr_req.dr_sm);
282  M0_ADDB2_ADD(M0_AVI_DIX_TO_MDIX, rid, mid);
283 }
284 
286  struct m0_sm_ast *ast)
287 {
288  struct m0_dix_req *req = ast->sa_datum;
289  struct m0_dix_meta_req *meta_req = req->dr_meta_req;
290  struct m0_dix_ldesc *ldesc;
291  enum m0_dix_req_state state = dix_req_state(req);
292  bool idx_op = dix_req_is_idxop(req);
293  uint32_t i;
294  uint32_t k;
295  int rc;
296  int rc2;
297 
298  M0_ENTRY("req %p", req);
300  rc = m0_dix_meta_generic_rc(meta_req);
301  if (rc == 0) {
302  M0_ASSERT(ergo(!idx_op, m0_dix_meta_req_nr(meta_req) == 1));
303  for (i = 0, k = 0; rc == 0 && i < req->dr_indices_nr; i++) {
304  switch(req->dr_indices[i].dd_layout.dl_type) {
305  case DIX_LTYPE_UNKNOWN:
307  rc2 = m0_dix_layout_rep_get(meta_req, k,
308  &req->dr_indices[k].dd_layout);
309  break;
310  case DIX_LTYPE_ID:
312  ldesc = &req->dr_indices[k].dd_layout.u.dl_desc;
313  rc2 = m0_dix_ldescr_rep_get(meta_req, k, ldesc);
314  break;
315  default:
316  /*
317  * Note, that CAS requests are not sent for
318  * layouts with DIX_LTYPE_DESCR.
319  */
320  M0_IMPOSSIBLE("Impossible layout type %d",
321  req->dr_indices[i].dd_layout.dl_type);
322  break;
323  }
324  if (rc2 != 0) {
325  /*
326  * Treat getting layout error as a fatal error
327  * for record operation, since the request is
328  * executed against only one index.
329  */
330  if (!idx_op)
331  rc = rc2;
332  else
333  req->dr_items[k].dxi_rc = rc2;
334  }
335  k++;
336  }
337  /* All replies for the meta request should be used. */
338  M0_ASSERT(k == m0_dix_meta_req_nr(meta_req));
339  }
340  m0_dix_meta_req_fini(meta_req);
341  m0_free0(&req->dr_meta_req);
342 
343  if (rc == 0) {
344  /*
345  * Stop request processing if there are no items which can
346  * potentially succeed.
347  */
348  if (!m0_exists(i, req->dr_items_nr,
349  req->dr_items[i].dxi_rc == 0)) {
351  /*
352  * If there are layouts identified by id then it's
353  * necessary to resolve id to layout descriptors. Check for
354  * state to avoid resolving layout ids in a loop.
355  */
356  } else if (dix_id_layouts_nr(req) > 0 &&
359  } else {
360  /*
361  * All (or at least some) layout descriptors are
362  * obtained successfully.
363  */
365  }
366  } else {
368  }
369 }
370 
371 static bool dix_layout_find_clink_cb(struct m0_clink *cl)
372 {
373  struct m0_dix_req *req = M0_AMB(req, cl, dr_clink);
374 
375  m0_clink_del(cl);
376  m0_clink_fini(cl);
377  req->dr_ast.sa_cb = dix_layout_find_ast_cb;
378  req->dr_ast.sa_datum = req;
379  m0_sm_ast_post(dix_req_smgrp(req), &req->dr_ast);
380  return true;
381 }
382 
383 static void dix_layout_find(struct m0_dix_req *req)
384 {
385  struct m0_dix_meta_req *meta_req;
386  struct m0_fid *fids;
387  struct m0_dix *indices;
388  uint32_t i;
389  uint32_t k;
390  uint32_t unknown_nr;
391  int rc;
392  M0_ENTRY();
393 
394  indices = req->dr_indices;
395  unknown_nr = dix_unknown_layouts_nr(req);
396 
397  M0_PRE(unknown_nr > 0);
398  M0_ALLOC_PTR(req->dr_meta_req);
399  M0_ALLOC_ARR(fids, unknown_nr);
400  if (fids == NULL || req->dr_meta_req == NULL) {
401  rc = M0_ERR(-ENOMEM);
402  goto err;
403  }
404  meta_req = req->dr_meta_req;
405  for (i = 0, k = 0; i < req->dr_indices_nr; i++)
407  fids[k++] = req->dr_indices[i].dd_fid;
408  m0_dix_meta_req_init(meta_req, req->dr_cli, dix_req_smgrp(req));
409  dix_to_mdix_map(req, meta_req);
411  m0_clink_add_lock(&meta_req->dmr_chan, &req->dr_clink);
412  /* Start loading layouts from CAS. */
413  rc = m0_dix_layout_get(meta_req, fids, unknown_nr);
414  if (rc != 0) {
415  m0_clink_del_lock(&req->dr_clink);
416  m0_clink_fini(&req->dr_clink);
417  m0_dix_meta_req_fini(meta_req);
418  }
419 
420 err:
421  if (rc != 0) {
422  m0_free0(&req->dr_meta_req);
424  } else {
426  }
427  m0_free(fids);
428  M0_LEAVE();
429 }
430 
431 static int dix_indices_copy(struct m0_dix **dst_indices,
432  const struct m0_dix *src_indices,
433  uint32_t indices_nr)
434 {
435  struct m0_dix *dst;
436  uint32_t i;
437  int rc = 0;
438 
439  M0_PRE(dst_indices != NULL);
440  M0_PRE(src_indices != NULL);
441  M0_PRE(indices_nr != 0);
442  M0_ALLOC_ARR(dst, indices_nr);
443  if (dst == NULL)
444  return M0_ERR(-ENOMEM);
445  for (i = 0; i < indices_nr; i++) {
446  rc = m0_dix_copy(&dst[i], &src_indices[i]);
447  if (rc != 0)
448  break;
449  }
450  if (rc != 0) {
451  for (i = 0; i < indices_nr; i++)
452  m0_dix_fini(&dst[i]);
453  m0_free(dst);
454  return M0_ERR(rc);
455  }
456  *dst_indices = dst;
457  return 0;
458 }
459 
461  const struct m0_dix *indices,
462  uint32_t indices_nr)
463 {
464  int rc;
465 
466  M0_PRE(indices != NULL);
467  M0_PRE(indices_nr != 0);
468  rc = dix_indices_copy(&req->dr_indices, indices, indices_nr);
469  if (rc == 0)
470  req->dr_indices_nr = indices_nr;
471  return rc;
472 }
473 
474 static struct m0_pool_version *dix_pver_find(const struct m0_dix_req *req,
475  const struct m0_fid *pver_fid)
476 {
477  return m0_pool_version_find(req->dr_cli->dx_pc, pver_fid);
478 }
479 
480 static void dix_idxop_ctx_free(struct m0_dix_idxop_ctx *idxop)
481 {
482  uint32_t i;
483 
484  for (i = 0; i < idxop->dcd_idxop_reqs_nr; i++)
486  m0_free0(&idxop->dcd_idxop_reqs);
487 }
488 
489 static void dix_idxop_item_rc_update(struct m0_dix_item *ditem,
490  struct m0_dix_req *req,
491  const struct m0_dix_cas_req *creq)
492 {
493  struct m0_cas_rec_reply crep;
494  const struct m0_cas_req *cas_req;
495  int rc;
496 
497  if (ditem->dxi_rc == 0) {
498  cas_req = &creq->ds_creq;
499  rc = creq->ds_rc ?:
500  m0_cas_req_generic_rc(cas_req);
501  if (rc == 0) {
502  switch (req->dr_type) {
503  case DIX_CREATE:
504  m0_cas_index_create_rep(cas_req, 0, &crep);
505  break;
506  case DIX_DELETE:
507  m0_cas_index_delete_rep(cas_req, 0, &crep);
508  break;
509  case DIX_CCTGS_LOOKUP:
510  m0_cas_index_lookup_rep(cas_req, 0, &crep);
511  break;
512  default:
513  M0_IMPOSSIBLE("Unknown type %u", req->dr_type);
514  }
515  rc = crep.crr_rc;
516  /*
517  * It is OK to get -ENOENT during 2nd phase, because
518  * catalogue can be deleted on 1st phase.
519  */
521  rc == -ENOENT)
522  rc = 0;
523  }
524  ditem->dxi_rc = rc;
525  }
526 }
527 
528 static void dix_idxop_completed(struct m0_sm_group *grp, struct m0_sm_ast *ast)
529 {
530  struct m0_dix_req *req = ast->sa_datum;
531  struct m0_dix_idxop_ctx *idxop_ctx = &req->dr_idxop;
532  struct m0_dix_idxop_req *idxop_req;
533  struct m0_dix_item *ditem;
534  struct m0_dix_cas_req *creq;
535  bool del_phase2 = false;
536  uint32_t i;
537  uint64_t j;
538  int rc;
539 
540  (void)grp;
541  M0_ENTRY("req %p", req);
542  for (i = 0; i < idxop_ctx->dcd_idxop_reqs_nr; i++) {
543  idxop_req = &idxop_ctx->dcd_idxop_reqs[i];
544  M0_ASSERT(idxop_req->dcr_index_no < req->dr_items_nr);
545  ditem = &req->dr_items[idxop_req->dcr_index_no];
546  for (j = 0; j < idxop_req->dcr_creqs_nr; j++) {
547  creq = &idxop_req->dcr_creqs[j];
548  dix_idxop_item_rc_update(ditem, req, creq);
549  if (ditem->dxi_rc == 0 && idxop_req->dcr_del_phase2) {
550  ditem->dxi_del_phase2 = true;
551  del_phase2 = true;
552  }
553  m0_cas_req_fini(&creq->ds_creq);
554  }
555  }
556  dix_idxop_ctx_free(idxop_ctx);
557  if (del_phase2) {
560  if (rc != 0)
562  } else {
564  }
565  M0_LEAVE();
566 }
567 
568 static bool dix_idxop_clink_cb(struct m0_clink *cl)
569 {
570  struct m0_dix_cas_req *creq = container_of(cl, struct m0_dix_cas_req,
571  ds_clink);
572  uint32_t state = creq->ds_creq.ccr_sm.sm_state;
573  struct m0_dix_idxop_ctx *idxop;
574  struct m0_dix_req *dreq;
575 
576  if (M0_IN(state, (CASREQ_FINAL, CASREQ_FAILURE))) {
577  dreq = creq->ds_parent;
578 
579  /* Update txid records in Client. */
580  if (dreq->dr_cli->dx_sync_rec_update != NULL)
581  dreq->dr_cli->dx_sync_rec_update(
582  dreq, creq->ds_creq.ccr_sess,
583  &creq->ds_creq.ccr_remid);
584 
585  m0_clink_del(cl);
586  m0_clink_fini(cl);
587  idxop = &creq->ds_parent->dr_idxop;
588  idxop->dcd_completed_nr++;
589  M0_PRE(idxop->dcd_completed_nr <= idxop->dcd_cas_reqs_nr);
590  if (idxop->dcd_completed_nr == idxop->dcd_cas_reqs_nr) {
592  idxop->dcd_ast.sa_datum = dreq;
593  m0_sm_ast_post(dix_req_smgrp(dreq), &idxop->dcd_ast);
594  }
595  }
596  return true;
597 }
598 
599 static int dix_idxop_pver_analyse(struct m0_dix_idxop_req *idxop_req,
600  struct m0_dix_req *dreq,
601  uint64_t *creqs_nr)
602 {
603  struct m0_pool_version *pver = idxop_req->dcr_pver;
604  struct m0_poolmach *pm = &pver->pv_mach;
605  struct m0_pools_common *pc = pver->pv_pc;
606  struct m0_pooldev *sdev;
607  enum m0_pool_nd_state state;
608  struct m0_reqh_service_ctx *cas_svc;
609  enum dix_req_type type = dreq->dr_type;
610  uint32_t i;
611  int rc = 0;
612  M0_ENTRY();
613 
615 
616  *creqs_nr = 0;
617  for (i = 0; i < pm->pm_state->pst_nr_devices; i++) {
618  sdev = &pm->pm_state->pst_devices_array[i];
619  cas_svc = pc->pc_dev2svc[sdev->pd_sdev_idx].pds_ctx;
620  if (cas_svc->sc_type != M0_CST_CAS) {
621  rc = M0_ERR_INFO(-EINVAL, "Incorrect service type %d",
622  cas_svc->sc_type);
623  break;
624  }
625 
626  state = sdev->pd_state;
627  /*
628  * It's impossible to create all component catalogues if some
629  * disk is not available (online or rebalancing). Also, it's
630  * impossible to check consistently that all component
631  * catalogues present if some disk is not online.
632  */
633  if ((state != M0_PNDS_ONLINE && type == DIX_CCTGS_LOOKUP) ||
634  (!M0_IN(state, (M0_PNDS_ONLINE, M0_PNDS_SNS_REBALANCING)) &&
635  type == DIX_CREATE)) {
636  rc = M0_ERR(-EIO);
637  break;
638  }
639 
640  /*
641  * Two-phase component catalogue removal is necessary if
642  * repair/re-balance is in progress.
643  * See dix/client.h, "Operation in degraded mode".
644  */
645  if (type == DIX_DELETE &&
646  dix_req_state(dreq) != DIXREQ_DEL_PHASE2 &&
647  M0_IN(state, (M0_PNDS_SNS_REPAIRING,
649  idxop_req->dcr_del_phase2 = true;
650 
651  /*
652  * Send CAS requests only on online or rebalancing drives.
653  * Actually, only DIX_DELETE only can send on devices
654  * selectively. DIX_CREATE, DIX_CCTGS_LOOKUP send whether to all
655  * drives in a pool or to none.
656  */
657  if (M0_IN(state, (M0_PNDS_ONLINE, M0_PNDS_SNS_REBALANCING)))
658  (*creqs_nr)++;
659  }
660 
661  if (rc == 0 && *creqs_nr == 0)
662  rc = M0_ERR(-EIO);
663 
664  if (rc != 0)
665  *creqs_nr = 0;
666  M0_POST(rc == 0 ? *creqs_nr > 0 : *creqs_nr == 0);
667  return M0_RC(rc);
668 }
669 
670 static int dix_idxop_req_send(struct m0_dix_idxop_req *idxop_req,
671  struct m0_dix_req *dreq,
672  uint64_t *reqs_acc)
673 {
674  struct m0_pool_version *pver = idxop_req->dcr_pver;
675  struct m0_poolmach *pm = &pver->pv_mach;
676  struct m0_pools_common *pc = pver->pv_pc;
677  struct m0_dix_cas_req *creq;
678  struct m0_pooldev *sdev;
679  uint32_t sdev_idx;
680  struct m0_fid cctg_fid;
681  struct m0_reqh_service_ctx *cas_svc;
682  uint32_t i;
683  uint32_t k;
684  struct m0_dix *index;
685  struct m0_cas_id cid;
686  uint32_t flags = dreq->dr_flags;
687  uint64_t creqs_nr;
688  int rc;
689  M0_ENTRY();
690 
692  rc = dix_idxop_pver_analyse(idxop_req, dreq, &creqs_nr);
693  if (rc != 0)
694  goto pmach_unlock;
695  M0_ALLOC_ARR(idxop_req->dcr_creqs, creqs_nr);
696  if (idxop_req->dcr_creqs == NULL) {
697  rc = M0_ERR(-ENOMEM);
698  goto pmach_unlock;
699  }
700  idxop_req->dcr_creqs_nr = creqs_nr;
701  k = 0;
702  for (i = 0; i < pm->pm_state->pst_nr_devices; i++) {
703  sdev = &pver->pv_mach.pm_state->pst_devices_array[i];
704  if (!M0_IN(sdev->pd_state, (M0_PNDS_ONLINE,
706  continue;
707  sdev_idx = sdev->pd_sdev_idx;
708  creq = &idxop_req->dcr_creqs[k++];
709  M0_LOG(M0_DEBUG, "creqs_nr=%" PRIu64 " this is the %d th creq=%p",
710  creqs_nr, k-1, creq);
711  creq->ds_parent = dreq;
712  cas_svc = pc->pc_dev2svc[sdev_idx].pds_ctx;
713  M0_ASSERT(cas_svc->sc_type == M0_CST_CAS);
714  m0_cas_req_init(&creq->ds_creq, &cas_svc->sc_rlink.rlk_sess,
715  dix_req_smgrp(dreq));
716  dix_to_cas_map(dreq, &creq->ds_creq);
718  m0_clink_add(&creq->ds_creq.ccr_sm.sm_chan, &creq->ds_clink);
719  index = &dreq->dr_indices[idxop_req->dcr_index_no];
720  m0_dix_fid_convert_dix2cctg(&index->dd_fid, &cctg_fid,
721  sdev_idx);
722  cid.ci_fid = cctg_fid;
723  M0_ASSERT(index->dd_layout.dl_type == DIX_LTYPE_DESCR);
724  cid.ci_layout.dl_type = index->dd_layout.dl_type;
725  rc = m0_dix_ldesc_copy(&cid.ci_layout.u.dl_desc,
726  &index->dd_layout.u.dl_desc);
727  if (rc == 0) {
728  switch (dreq->dr_type) {
729  case DIX_CREATE:
730  rc = m0_cas_index_create(&creq->ds_creq, &cid,
731  1, dreq->dr_dtx);
732  break;
733  case DIX_DELETE:
734  if (idxop_req->dcr_del_phase2)
735  flags |= COF_DEL_LOCK;
736  rc = m0_cas_index_delete(&creq->ds_creq, &cid,
737  1, dreq->dr_dtx,
738  flags);
739  break;
740  case DIX_CCTGS_LOOKUP:
741  rc = m0_cas_index_lookup(&creq->ds_creq, &cid,
742  1);
743  break;
744  default:
745  M0_IMPOSSIBLE("Unknown type %u", dreq->dr_type);
746  }
747  }
748  m0_cas_id_fini(&cid);
749  if (rc != 0) {
750  creq->ds_rc = M0_ERR(rc);
751  m0_clink_del(&creq->ds_clink);
752  m0_clink_fini(&creq->ds_clink);
753  /*
754  * index->dd_layout.u.dl_desc will be finalised in
755  * m0_dix_req_fini().
756  */
757  } else {
758  (*reqs_acc)++;
759  }
760  }
761  M0_ASSERT(k == creqs_nr);
762 pmach_unlock:
764  return M0_RC(rc);
765 }
766 
768  struct m0_sm_ast *ast)
769 {
770  struct m0_dix_req *req = ast->sa_datum;
771  struct m0_dix_meta_req *meta_req = req->dr_meta_req;
772  struct m0_dix_item *item;
773  uint64_t fids_nr;
774  int i;
775  int k;
776  /*
777  * Inidicates whether request processing should be continued.
778  * The request processing is stopped if all items in the user input
779  * vector are failed or CROW is requested for CREATE operation.
780  */
781  bool cont = false;
782  bool crow = !!(req->dr_flags & COF_CROW);
783  int rc;
784 
785  fids_nr = m0_count(i, req->dr_items_nr, req->dr_items[i].dxi_rc == 0);
786  M0_ASSERT(fids_nr > 0);
787  rc = m0_dix_meta_generic_rc(meta_req);
788  if (rc == 0) {
789  k = 0;
790  for (i = 0; i < req->dr_items_nr; i++) {
791  item = &req->dr_items[i];
792  if (item->dxi_rc == 0) {
793  item->dxi_rc = m0_dix_meta_item_rc(meta_req, k);
794  cont = cont || item->dxi_rc == 0;
795  k++;
796  }
797  }
798  M0_ASSERT(k == fids_nr);
799  if (!cont)
800  M0_LOG(M0_ERROR, "All items are failed");
801  /*
802  * If CROW is requested for CREATE operation, then component
803  * catalogues shouldn't be created => no CAS create requests
804  * should be sent.
805  */
806  cont = cont && !(req->dr_type == DIX_CREATE && crow);
807  if (cont)
809  }
810 
811  m0_dix_meta_req_fini(meta_req);
812  m0_free0(&req->dr_meta_req);
813  if (rc == 0)
814  dix_req_state_set(req, !cont ?
816  else
818 }
819 
821 {
822  struct m0_dix_req *req = container_of(cl, struct m0_dix_req, dr_clink);
823 
824  /*
825  * Sining: no need to update SYNC records in Client from this callback
826  * as it is invoked in meta.c::dix_meta_op_done_cb() and reply fops
827  * have been processed to update SYNC records in dix_cas_rop_clink_cb()
828  * before it.
829  */
830 
831  m0_clink_del(cl);
832  m0_clink_fini(cl);
833  req->dr_ast.sa_cb = dix_idxop_meta_update_ast_cb;
834  req->dr_ast.sa_datum = req;
835  m0_sm_ast_post(dix_req_smgrp(req), &req->dr_ast);
836  return true;
837 }
838 
840 {
841  struct m0_dix_meta_req *meta_req;
842  struct m0_fid *fids;
843  struct m0_dix_layout *layouts = NULL;
844  uint32_t fids_nr;
845  bool create = req->dr_type == DIX_CREATE;
846  uint64_t i;
847  uint64_t k;
848  int rc;
849 
850  M0_ENTRY();
851  M0_PRE(M0_IN(req->dr_type, (DIX_CREATE, DIX_DELETE)));
852  M0_ASSERT(req->dr_indices_nr == req->dr_items_nr);
853  fids_nr = m0_count(i, req->dr_items_nr, req->dr_items[i].dxi_rc == 0);
854  M0_ASSERT(fids_nr > 0);
855  M0_ALLOC_PTR(req->dr_meta_req);
856  M0_ALLOC_ARR(fids, fids_nr);
857  if (create)
858  M0_ALLOC_ARR(layouts, fids_nr);
859  if (fids == NULL || (create && layouts == NULL) ||
860  req->dr_meta_req == NULL) {
861  m0_free(fids);
862  m0_free(layouts);
863  m0_free(req->dr_meta_req);
864  return M0_ERR(-ENOMEM);
865  }
866 
867  meta_req = req->dr_meta_req;
868  k = 0;
869  for (i = 0; i < req->dr_items_nr; i++) {
870  if (req->dr_items[i].dxi_rc == 0) {
871  if (create) {
872  fids[k] = req->dr_orig_indices[i].dd_fid;
873  layouts[k] = req->dr_orig_indices[i].dd_layout;
874  } else {
875  fids[k] = req->dr_indices[i].dd_fid;
876  }
877  k++;
878  }
879  }
880  M0_ASSERT(k == fids_nr);
881 
882  m0_dix_meta_req_init(meta_req, req->dr_cli, dix_req_smgrp(req));
883  dix_to_mdix_map(req, meta_req);
884  /* Pass down the SYNC datum. */
885  meta_req->dmr_req.dr_sync_datum = req->dr_sync_datum;
887  m0_clink_add_lock(&meta_req->dmr_chan, &req->dr_clink);
888  rc = create ?
889  m0_dix_layout_put(meta_req, fids, layouts, fids_nr, req->dr_flags) :
890  m0_dix_layout_del(meta_req, fids, fids_nr);
891  if (rc != 0) {
892  m0_clink_del_lock(&req->dr_clink);
893  m0_clink_fini(&req->dr_clink);
894  m0_dix_meta_req_fini(meta_req);
895  m0_free0(&req->dr_meta_req);
896  }
897  m0_free(layouts);
898  m0_free(fids);
899  return M0_RC(rc);
900 }
901 
909 static bool dix_item_should_be_sent(const struct m0_dix_req *req, uint32_t i)
910 {
911  return dix_req_state(req) == DIXREQ_DEL_PHASE2 ?
912  req->dr_items[i].dxi_del_phase2 :
913  req->dr_items[i].dxi_rc == 0;
914 }
915 
916 static int dix_idxop_reqs_send(struct m0_dix_req *req)
917 {
918  struct m0_dix *indices = req->dr_indices;
919  struct m0_dix_idxop_ctx *idxop = &req->dr_idxop;
920  struct m0_dix_idxop_req *idxop_req;
921  struct m0_dix_layout *layout;
922  uint32_t reqs_nr;
923  uint32_t i;
924  uint32_t k;
925  uint64_t cas_nr = 0;
926  int rc;
927 
928  M0_ENTRY();
932  reqs_nr = m0_count(i, req->dr_items_nr,
934  M0_PRE(reqs_nr > 0);
935  M0_SET0(idxop);
936  M0_ALLOC_ARR(idxop->dcd_idxop_reqs, reqs_nr);
937  if (idxop->dcd_idxop_reqs == NULL)
938  return M0_ERR(-ENOMEM);
939  idxop->dcd_idxop_reqs_nr = reqs_nr;
940  for (i = 0, k = 0; i < req->dr_items_nr; i++) {
941  if (dix_item_should_be_sent(req, i)) {
942  layout = &indices[i].dd_layout;
943  M0_PRE(layout->dl_type == DIX_LTYPE_DESCR);
944  idxop_req = &idxop->dcd_idxop_reqs[k++];
945  idxop_req->dcr_index_no = i;
946  idxop_req->dcr_pver = dix_pver_find(req,
947  &layout->u.dl_desc.ld_pver);
948  rc = dix_idxop_req_send(idxop_req, req, &cas_nr);
949  if (rc != 0)
950  req->dr_items[i].dxi_rc = M0_ERR(rc);
951  }
952  }
953  if (cas_nr == 0) {
954  dix_idxop_ctx_free(idxop);
955  return M0_ERR(-EIO);
956  } else {
957  idxop->dcd_completed_nr = 0;
958  idxop->dcd_cas_reqs_nr = cas_nr;
959  }
960  return M0_RC(0);
961 }
962 
963 static void dix_idxop(struct m0_dix_req *req)
964 {
965  enum m0_dix_req_state next_state = DIXREQ_INVALID;
966  int rc;
967  M0_ENTRY();
968 
969  M0_PRE(dix_resolved_nr(req) > 0);
970  /*
971  * Put/delete ordinary indices layouts in 'layout' meta-index.
972  */
973  if (!req->dr_is_meta &&
974  M0_IN(req->dr_type, (DIX_CREATE, DIX_DELETE)) &&
975  !(req->dr_flags & COF_SKIP_LAYOUT)) {
977  next_state = DIXREQ_META_UPDATE;
978  } else {
980  next_state = DIXREQ_INPROGRESS;
981  }
982 
983  if (rc == 0)
984  dix_req_state_set(req, next_state);
985  else
987  M0_LEAVE();
988 }
989 
990 M0_INTERNAL int m0_dix_create(struct m0_dix_req *req,
991  const struct m0_dix *indices,
992  uint32_t indices_nr,
993  struct m0_dtx *dtx,
994  uint32_t flags)
995 {
996  int rc;
997 
998  M0_ENTRY();
999  /*
1000  * User should provide layouts of each index to create in the form of
1001  * layout descriptor or layout id.
1002  */
1003  M0_PRE(m0_forall(i, indices_nr,
1004  indices[i].dd_layout.dl_type != DIX_LTYPE_UNKNOWN));
1005  M0_PRE(ergo(req->dr_is_meta, dix_id_layouts_nr(req) == 0));
1006  M0_PRE((flags & ~(COF_CROW | COF_SKIP_LAYOUT)) == 0);
1007  req->dr_dtx = dtx;
1008  /*
1009  * Save indices identifiers in two arrays. Indices identifiers in
1010  * req->dr_indices will be overwritten once layout ids (if any) are
1011  * resolved into layout descriptors. Record in 'layout' index should be
1012  * inserted with the layout requested by a user, not the resolved one.
1013  */
1014  rc = dix_req_indices_copy(req, indices, indices_nr) ?:
1015  dix_indices_copy(&req->dr_orig_indices, indices, indices_nr);
1016  if (rc != 0)
1017  return M0_ERR(rc);
1018  M0_ALLOC_ARR(req->dr_items, indices_nr);
1019  if (req->dr_items == NULL)
1020  /*
1021  * Cleanup of req->dr_indices and req->dr_orig_indices will be
1022  * done in m0_dix_req_fini().
1023  */
1024  return M0_ERR(-ENOMEM);
1025  req->dr_items_nr = indices_nr;
1026  req->dr_type = DIX_CREATE;
1027  req->dr_flags = flags;
1028  dix_discovery(req);
1029  return M0_RC(0);
1030 }
1031 
1032 static void dix_ldescr_resolve(struct m0_dix_req *req)
1033 {
1034  struct m0_dix *indices = req->dr_indices;
1035  uint32_t id_nr = dix_id_layouts_nr(req);
1036  struct m0_dix_meta_req *meta_req;
1037  uint64_t *lids;
1038  int i;
1039  int k;
1040  int rc;
1041  M0_ENTRY();
1042 
1043  /*
1044  * If layout descriptors have DIX_LTYPE_ID, then they should be loaded
1045  * via m0_dix_ldescr_get() in order to find out actual layout.
1046  */
1047  M0_ALLOC_PTR(req->dr_meta_req);
1048  M0_ALLOC_ARR(lids, id_nr);
1049  if (lids == NULL || req->dr_meta_req == NULL) {
1050  rc = M0_ERR(-ENOMEM);
1051  goto err;
1052  }
1053  for (i = 0, k = 0; i < req->dr_indices_nr; i++)
1054  if (indices[i].dd_layout.dl_type == DIX_LTYPE_ID)
1055  lids[k++] = indices[i].dd_layout.u.dl_id;
1056  meta_req = req->dr_meta_req;
1057  m0_dix_meta_req_init(meta_req, req->dr_cli, dix_req_smgrp(req));
1058  dix_to_mdix_map(req, meta_req);
1060  m0_clink_add_lock(&meta_req->dmr_chan, &req->dr_clink);
1061  /* Start loading layout descriptors from CAS. */
1062  rc = m0_dix_ldescr_get(meta_req, lids, id_nr);
1063  if (rc != 0) {
1064  m0_clink_del_lock(&req->dr_clink);
1065  m0_clink_fini(&req->dr_clink);
1066  m0_dix_meta_req_fini(meta_req);
1067  }
1068 
1069 err:
1070  if (rc != 0) {
1071  m0_free0(&req->dr_meta_req);
1073  } else {
1075  }
1076  m0_free(lids);
1077  M0_LEAVE();
1078 }
1079 
1080 static void addb2_add_dix_req_attrs(const struct m0_dix_req *req)
1081 {
1082  uint64_t sm_id = m0_sm_id_get(&req->dr_sm);
1083 
1084  M0_ADDB2_ADD(M0_AVI_ATTR, sm_id,
1085  M0_AVI_DIX_REQ_ATTR_IS_META, req->dr_is_meta);
1086  M0_ADDB2_ADD(M0_AVI_ATTR, sm_id,
1087  M0_AVI_DIX_REQ_ATTR_REQ_TYPE, req->dr_type);
1088  M0_ADDB2_ADD(M0_AVI_ATTR, sm_id,
1089  M0_AVI_DIX_REQ_ATTR_ITEMS_NR, req->dr_items_nr);
1090  M0_ADDB2_ADD(M0_AVI_ATTR, sm_id,
1091  M0_AVI_DIX_REQ_ATTR_INDICES_NR, req->dr_indices_nr);
1092  if (req->dr_keys != NULL)
1094  req->dr_keys->ov_vec.v_nr);
1095  if (req->dr_vals != NULL)
1097  req->dr_vals->ov_vec.v_nr);
1098 }
1099 
1101 {
1102  M0_ENTRY();
1105 
1106  /*
1107  * All layouts have been resolved, all types are DIX_LTYPE_DESCR,
1108  * perform dix operation.
1109  */
1110  switch (req->dr_type) {
1111  case DIX_CREATE:
1112  case DIX_DELETE:
1113  case DIX_CCTGS_LOOKUP:
1114  dix_idxop(req);
1115  break;
1116  case DIX_GET:
1117  case DIX_PUT:
1118  case DIX_DEL:
1119  case DIX_NEXT:
1120  dix_rop(req);
1121  break;
1122  default:
1123  M0_IMPOSSIBLE("Unknown request type %u", req->dr_type);
1124  }
1125  M0_LEAVE();
1126 }
1127 
1128 static void dix_discovery_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1129 {
1130  struct m0_dix_req *req = container_of(ast, struct m0_dix_req, dr_ast);
1131  M0_ENTRY();
1132 
1133  (void)grp;
1134  if (dix_unknown_layouts_nr(req) > 0)
1136  else if (dix_id_layouts_nr(req) > 0)
1138  else
1140  M0_LEAVE();
1141 }
1142 
1143 static void dix_discovery(struct m0_dix_req *req)
1144 {
1145  /* Entry point to start discovering and resolving layout descriptors. */
1146  req->dr_ast.sa_cb = dix_discovery_ast;
1147  req->dr_ast.sa_datum = req;
1148  m0_sm_ast_post(dix_req_smgrp(req), &req->dr_ast);
1149 }
1150 
1152 void m0_dix_req_cancel(struct m0_dix_req *dreq)
1153 {
1154  struct m0_fop *fop;
1155  struct m0_dix_rop_ctx *rop;
1156  struct m0_dix_cas_rop *cas_rop;
1157 
1158  M0_ENTRY();
1159  switch (dreq->dr_type) {
1160  case DIX_GET:
1161  case DIX_PUT:
1162  case DIX_DEL:
1163  case DIX_NEXT:
1164  rop = dreq->dr_rop;
1165  if (rop == NULL)
1166  return;
1167  M0_LOG(M0_DEBUG, "dg_completed_nr=%" PRIu64 " "
1168  "dg_cas_reqs_nr=%" PRIu64 " dr_type=%d",
1169  rop->dg_completed_nr, rop->dg_cas_reqs_nr,
1170  dreq->dr_type);
1171  if (rop->dg_completed_nr < rop->dg_cas_reqs_nr) {
1172  m0_tl_for(cas_rop, &rop->dg_cas_reqs, cas_rop) {
1173  fop = cas_rop->crp_creq.ccr_fop;
1174  if (fop != NULL)
1176  } m0_tl_endfor;
1177  }
1178  break;
1179  case DIX_CREATE:
1180  case DIX_DELETE:
1181  case DIX_CCTGS_LOOKUP:
1182  /*
1183  * rpc item not available to cancel after launching index
1184  * create / delete / lookup operation so no-op
1185  */
1186  break;
1187  }
1188 }
1189 
1190 M0_INTERNAL int m0_dix_delete(struct m0_dix_req *req,
1191  const struct m0_dix *indices,
1192  uint64_t indices_nr,
1193  struct m0_dtx *dtx,
1194  uint32_t flags)
1195 {
1196  int rc;
1197 
1198  M0_ENTRY();
1199  M0_PRE((flags & ~(COF_CROW | COF_SKIP_LAYOUT)) == 0);
1200  req->dr_dtx = dtx;
1201  rc = dix_req_indices_copy(req, indices, indices_nr);
1202  if (rc != 0)
1203  return M0_ERR(rc);
1204  M0_ALLOC_ARR(req->dr_items, indices_nr);
1205  if (req->dr_items == NULL)
1206  return M0_ERR(-ENOMEM);
1207  req->dr_items_nr = indices_nr;
1208  req->dr_type = DIX_DELETE;
1209  req->dr_flags = flags;
1210  dix_discovery(req);
1211  return M0_RC(0);
1212 }
1213 
1214 M0_INTERNAL int m0_dix_cctgs_lookup(struct m0_dix_req *req,
1215  const struct m0_dix *indices,
1216  uint32_t indices_nr)
1217 {
1218  int rc;
1219 
1220  M0_ENTRY();
1221  rc = dix_req_indices_copy(req, indices, indices_nr);
1222  if (rc != 0)
1223  return M0_ERR(rc);
1224  M0_ALLOC_ARR(req->dr_items, indices_nr);
1225  if (req->dr_items == NULL)
1226  return M0_ERR(-ENOMEM);
1227  req->dr_items_nr = indices_nr;
1228  req->dr_type = DIX_CCTGS_LOOKUP;
1229  dix_discovery(req);
1230  return M0_RC(0);
1231 }
1232 
1233 static int dix_rec_op_init(struct m0_dix_rec_op *rec_op,
1234  struct m0_dix_req *req,
1235  struct m0_dix_cli *cli,
1236  struct m0_pool_version *pver,
1237  struct m0_dix *dix,
1238  struct m0_buf *key,
1239  uint64_t user_item)
1240 {
1241  int rc;
1242 
1244  rc = m0_dix_layout_iter_init(&rec_op->dgp_iter, &dix->dd_fid,
1245  cli->dx_ldom, pver,
1246  &dix->dd_layout.u.dl_desc, key);
1247  if (rc != 0)
1248  return M0_ERR(rc);
1249  rec_op->dgp_units_nr = dix_rop_tgt_iter_max(req, rec_op);
1250  M0_ALLOC_ARR(rec_op->dgp_units, rec_op->dgp_units_nr);
1251  if (rec_op->dgp_units == NULL) {
1253  return M0_ERR(rc);
1254  }
1255  rec_op->dgp_item = user_item;
1256  rec_op->dgp_key = *key;
1257  return 0;
1258 }
1259 
1260 static void dix_rec_op_fini(struct m0_dix_rec_op *rec_op)
1261 {
1263  m0_free(rec_op->dgp_units);
1264 }
1265 
1266 static int dix_cas_rop_alloc(struct m0_dix_req *req, uint32_t sdev,
1267  struct m0_dix_cas_rop **cas_rop)
1268 {
1269  struct m0_dix_rop_ctx *rop = req->dr_rop;
1270  M0_ENTRY();
1271 
1272  M0_ALLOC_PTR(*cas_rop);
1273  if (*cas_rop == NULL)
1274  return M0_ERR(-ENOMEM);
1275  (*cas_rop)->crp_parent = req;
1276  (*cas_rop)->crp_sdev_idx = sdev;
1277  (*cas_rop)->crp_flags = req->dr_flags;
1278  cas_rop_tlink_init_at(*cas_rop, &rop->dg_cas_reqs);
1279 
1280  return M0_RC_INFO(0, "dix req=%p rop=%p cas_rop=%p sdev=%u",
1281  req, rop, *cas_rop, sdev);
1282 }
1283 
1284 static void dix_cas_rop_fini(struct m0_dix_cas_rop *cas_rop)
1285 {
1286  m0_free(cas_rop->crp_attrs);
1287  m0_bufvec_free2(&cas_rop->crp_keys);
1288  m0_bufvec_free2(&cas_rop->crp_vals);
1289  cas_rop_tlink_fini(cas_rop);
1290 }
1291 
1292 static void dix_cas_rops_fini(struct m0_tl *cas_rops)
1293 {
1294  struct m0_dix_cas_rop *cas_rop;
1295 
1296  m0_tl_teardown(cas_rop, cas_rops, cas_rop) {
1297  dix_cas_rop_fini(cas_rop);
1298  m0_free(cas_rop);
1299  }
1300 }
1301 
1302 static int dix_rop_ctx_init(struct m0_dix_req *req,
1303  struct m0_dix_rop_ctx *rop,
1304  const struct m0_bufvec *keys,
1305  uint64_t *indices)
1306 {
1307  struct m0_dix *dix = &req->dr_indices[0];
1308  struct m0_dix_ldesc *ldesc;
1309  uint32_t keys_nr;
1310  struct m0_buf key;
1311  uint32_t i;
1312  int rc = 0;
1313 
1314  M0_ENTRY();
1315  M0_PRE(M0_IS0(rop));
1316  M0_PRE(req->dr_indices_nr == 1);
1318  M0_PRE(keys != NULL);
1319  keys_nr = keys->ov_vec.v_nr;
1320  M0_PRE(keys_nr != 0);
1321  ldesc = &dix->dd_layout.u.dl_desc;
1322  rop->dg_pver = dix_pver_find(req, &ldesc->ld_pver);
1323  M0_ALLOC_ARR(rop->dg_rec_ops, keys_nr);
1325  if (rop->dg_rec_ops == NULL || rop->dg_target_rop == NULL)
1326  return M0_ERR(-ENOMEM);
1327  for (i = 0; i < keys_nr; i++) {
1328  key = M0_BUF_INIT(keys->ov_vec.v_count[i], keys->ov_buf[i]);
1329  rc = dix_rec_op_init(&rop->dg_rec_ops[i], req, req->dr_cli,
1330  rop->dg_pver, &req->dr_indices[0], &key,
1331  indices == NULL ? i : indices[i]);
1332  if (rc != 0) {
1333  for (i = 0; i < rop->dg_rec_ops_nr; i++)
1334  dix_rec_op_fini(&rop->dg_rec_ops[i]);
1335  break;
1336  }
1337  rop->dg_rec_ops_nr++;
1338  }
1339  cas_rop_tlist_init(&rop->dg_cas_reqs);
1340  return M0_RC(rc);
1341 }
1342 
1343 static void dix_rop_ctx_fini(struct m0_dix_rop_ctx *rop)
1344 {
1345  uint32_t i;
1346 
1347  for (i = 0; i < rop->dg_rec_ops_nr; i++)
1348  dix_rec_op_fini(&rop->dg_rec_ops[i]);
1349  m0_free(rop->dg_rec_ops);
1350  m0_free(rop->dg_target_rop);
1352  cas_rop_tlist_fini(&rop->dg_cas_reqs);
1353  M0_SET0(rop);
1354 }
1355 
1356 static void dix__rop(struct m0_dix_req *req, const struct m0_bufvec *keys,
1357  uint64_t *indices)
1358 {
1359  struct m0_dix_rop_ctx *rop;
1360  uint32_t keys_nr;
1361  int rc;
1362  M0_ENTRY();
1363 
1364  M0_PRE(keys != NULL);
1365  M0_PRE(req->dr_indices_nr == 1);
1366 
1367  keys_nr = keys->ov_vec.v_nr;
1368  M0_PRE(keys_nr != 0);
1369  /* We support only one KV pair per request in DTM0. */
1370  M0_PRE(ergo(req->dr_dtx != NULL, keys_nr == 1));
1371  M0_ALLOC_PTR(rop);
1372  if (rop == NULL) {
1373  dix_req_failure(req, M0_ERR(-ENOMEM));
1374  return;
1375  }
1376  rc = dix_rop_ctx_init(req, rop, keys, indices);
1377  if (rc != 0) {
1379  return;
1380  }
1381  req->dr_rop = rop;
1383  rc = dix_cas_rops_alloc(req) ?:
1386  if (rc != 0) {
1387  dix_rop_ctx_fini(rop);
1389  } else if (dix_req_state(req) != DIXREQ_DEL_PHASE2)
1391  M0_LEAVE();
1392 }
1393 
1394 static void dix_rop(struct m0_dix_req *req)
1395 {
1396  M0_PRE(req->dr_indices_nr == 1);
1398  M0_PRE(req->dr_keys != NULL);
1399  M0_ENTRY();
1400 
1401  dix__rop(req, req->dr_keys, NULL);
1402  M0_LEAVE();
1403 }
1404 
1405 static void dix_item_rc_update(struct m0_dix_req *req,
1406  struct m0_cas_req *creq,
1407  uint64_t key_idx,
1408  struct m0_dix_item *ditem)
1409 {
1410  struct m0_cas_rec_reply rep;
1411  struct m0_cas_get_reply get_rep;
1412  int rc;
1413  enum dix_req_type rtype = req->dr_type;
1414 
1415  rc = m0_cas_req_generic_rc(creq);
1416  if (rc == 0) {
1417  switch (rtype) {
1418  case DIX_GET:
1419  m0_cas_get_rep(creq, key_idx, &get_rep);
1420  rc = get_rep.cge_rc;
1421  if (rc == 0) {
1422  ditem->dxi_val = get_rep.cge_val;
1423  /* Value will be freed at m0_dix_req_fini(). */
1424  m0_cas_rep_mlock(creq, key_idx);
1425  }
1426  break;
1427  case DIX_PUT:
1428  m0_cas_put_rep(creq, key_idx, &rep);
1429  rc = rep.crr_rc;
1430  break;
1431  case DIX_DEL:
1432  m0_cas_del_rep(creq, key_idx, &rep);
1433  /*
1434  * It is possible that repair process didn't copy
1435  * replica to spare disk yet. Ignore such an error.
1436  */
1438  rep.crr_rc == -ENOENT)
1439  rep.crr_rc = 0;
1440  rc = rep.crr_rc;
1441  break;
1442  default:
1443  M0_IMPOSSIBLE("Incorrect type %u", rtype);
1444  }
1445  }
1446  ditem->dxi_rc = rc;
1447 }
1448 
1450 {
1451  return item->dxi_rc != 0 && item->dxi_rc != -ENOENT;
1452 }
1453 
1454 static bool dix_item_parity_unit_is_last(const struct m0_dix_req *req,
1455  const struct m0_dix_item *item)
1456 {
1457  struct m0_pool_version *pver;
1458 
1459  pver = m0_dix_pver(req->dr_cli, &req->dr_indices[0]);
1460  return item->dxi_pg_unit == pver->pv_attr.pa_N + pver->pv_attr.pa_K - 1;
1461 }
1462 
1463 static void dix_get_req_resend(struct m0_dix_req *req)
1464 {
1465  struct m0_bufvec keys;
1466  uint64_t *indices;
1467  uint32_t keys_nr;
1468  uint32_t i;
1469  uint32_t k = 0;
1470  int rc;
1471  M0_ENTRY();
1472 
1473  keys_nr = m0_count(i, req->dr_items_nr,
1474  dix_item_get_has_failed(&req->dr_items[i]) &&
1475  !dix_item_parity_unit_is_last(req, &req->dr_items[i]));
1476  if (keys_nr == 0) {
1477  /*
1478  * Some records are not retrieved from both data and parity
1479  * units locations.
1480  */
1481  rc = M0_ERR(-EHOSTUNREACH);
1482  goto end;
1483  }
1484  rc = m0_bufvec_empty_alloc(&keys, keys_nr);
1485  M0_ALLOC_ARR(indices, keys_nr);
1486  if (rc != 0 || indices == NULL) {
1487  rc = rc ?: M0_ERR(-ENOMEM);
1488  goto free;
1489  }
1490  for (i = 0; i < req->dr_items_nr; i++) {
1491  if (!dix_item_get_has_failed(&req->dr_items[i]))
1492  continue;
1493  /*
1494  * Clear error code in order to update it successfully on
1495  * request completion. Otherwise, it wouldn't be overwritten
1496  * because it is possible that several CAS requests are sent
1497  * for one item and it holds error code for the first failed
1498  * request.
1499  */
1500  req->dr_items[i].dxi_rc = 0;
1501  req->dr_items[i].dxi_pg_unit++;
1502  keys.ov_vec.v_count[k] = req->dr_keys->ov_vec.v_count[i];
1503  keys.ov_buf[k] = req->dr_keys->ov_buf[i];
1504  indices[k] = i;
1505  k++;
1506  }
1507 
1508  dix__rop(req, &keys, indices);
1509 free:
1510  m0_bufvec_free2(&keys);
1511  m0_free(indices);
1512 end:
1513  if (rc != 0)
1515  M0_LEAVE();
1516 }
1517 
1518 static bool dix_del_phase2_is_needed(const struct m0_dix_rec_op *rec_op)
1519 {
1520  return m0_exists(i, rec_op->dgp_units_nr,
1521  rec_op->dgp_units[i].dpu_del_phase2);
1522 }
1523 
1525  struct m0_dix_rop_ctx **out)
1526 {
1527  struct m0_dix_rop_ctx *cur_rop = req->dr_rop;
1528  struct m0_dix_rop_ctx *out_rop;
1529  struct m0_dix_rec_op *src_rec_op;
1530  struct m0_dix_rec_op *dst_rec_op;
1531  struct m0_bufvec keys;
1532  uint64_t *indices;
1533  uint32_t keys_nr;
1534  uint32_t i;
1535  uint32_t j;
1536  uint32_t k = 0;
1537  int rc;
1538 
1539  keys_nr = m0_count(i, cur_rop->dg_rec_ops_nr,
1540  dix_del_phase2_is_needed(&cur_rop->dg_rec_ops[i]));
1541 
1542  if (keys_nr == 0)
1543  return 0;
1544 
1545  rc = m0_bufvec_empty_alloc(&keys, keys_nr);
1546  M0_ALLOC_ARR(indices, keys_nr);
1547  M0_ALLOC_PTR(out_rop);
1548  if (rc != 0 || indices == NULL || out_rop == NULL) {
1549  rc = M0_ERR(rc ?: -ENOMEM);
1550  goto free;
1551  }
1552  for (i = 0; i < cur_rop->dg_rec_ops_nr; i++) {
1553  if (!dix_del_phase2_is_needed(&cur_rop->dg_rec_ops[i]))
1554  continue;
1555  keys.ov_vec.v_count[k] = req->dr_keys->ov_vec.v_count[i];
1556  keys.ov_buf[k] = req->dr_keys->ov_buf[i];
1557  indices[k] = i;
1558  k++;
1559  }
1560 
1561  rc = dix_rop_ctx_init(req, out_rop, &keys, indices);
1562  if (rc != 0)
1563  goto free;
1564  k = 0;
1565  for (i = 0; i < cur_rop->dg_rec_ops_nr; i++) {
1566  src_rec_op = &cur_rop->dg_rec_ops[i];
1567  if (!dix_del_phase2_is_needed(src_rec_op))
1568  continue;
1569  dst_rec_op = &out_rop->dg_rec_ops[k++];
1570  M0_ASSERT(src_rec_op->dgp_units_nr == dst_rec_op->dgp_units_nr);
1571  for (j = 0; j < src_rec_op->dgp_units_nr; j++)
1572  dst_rec_op->dgp_units[j] = src_rec_op->dgp_units[j];
1573  }
1574 
1575 free:
1576  m0_bufvec_free2(&keys);
1577  m0_free(indices);
1578  if (rc == 0) {
1579  rc = keys_nr;
1580  *out = out_rop;
1581  } else
1582  m0_free(out_rop);
1583  return M0_RC(rc);
1584 }
1585 
1586 static void dix_rop_del_phase2(struct m0_dix_req *req)
1587 {
1588  int rc;
1589 
1591 
1592  rc = dix_cas_rops_alloc(req) ?:
1595 
1596  if (rc != 0) {
1597  dix_rop_ctx_fini(req->dr_rop);
1599  }
1600 }
1601 
1602 static void dix_cas_rop_rc_update(struct m0_dix_cas_rop *cas_rop, int rc)
1603 {
1604  struct m0_dix_req *req = cas_rop->crp_parent;
1605  struct m0_dix_item *ditem;
1606  uint64_t item_idx;
1607  uint32_t i;
1608 
1609  for (i = 0; i < cas_rop->crp_keys_nr; i++) {
1610  item_idx = cas_rop->crp_attrs[i].cra_item;
1611  ditem = &req->dr_items[item_idx];
1612  if (ditem->dxi_rc != 0)
1613  continue;
1614  if (rc == 0)
1615  dix_item_rc_update(req, &cas_rop->crp_creq, i, ditem);
1616  else
1617  ditem->dxi_rc = M0_ERR(rc);
1618  }
1619 }
1620 
1621 static void dix_rop_completed(struct m0_sm_group *grp, struct m0_sm_ast *ast)
1622 {
1623  struct m0_dix_req *req = ast->sa_datum;
1624  struct m0_dix_rop_ctx *rop = req->dr_rop;
1625  struct m0_dix_rop_ctx *rop_del_phase2 = NULL;
1626  bool del_phase2 = false;
1627  struct m0_dix_cas_rop *cas_rop;
1628 
1629  (void)grp;
1630  if (req->dr_type == DIX_NEXT)
1632  else {
1633  /*
1634  * Consider DIX request to be successful if there is at least
1635  * one successful CAS request.
1636  */
1637  if (m0_tl_forall(cas_rop, cas_rop,
1638  &rop->dg_cas_reqs,
1639  cas_rop->crp_creq.ccr_sm.sm_rc != 0))
1640  dix_cas_rop_rc_update(cas_rop_tlist_tail(
1641  &rop->dg_cas_reqs), 0);
1642 
1643  m0_tl_for (cas_rop, &rop->dg_cas_reqs, cas_rop) {
1644  if (cas_rop->crp_creq.ccr_sm.sm_rc == 0)
1645  dix_cas_rop_rc_update(cas_rop, 0);
1646  m0_cas_req_fini(&cas_rop->crp_creq);
1647  } m0_tl_endfor;
1648  }
1649 
1650  if (req->dr_type == DIX_DEL &&
1652  del_phase2 = dix_rop_del_phase2_rop(req, &rop_del_phase2) > 0;
1653 
1654  dix_rop_ctx_fini(rop);
1655  if (req->dr_type == DIX_GET &&
1656  m0_exists(i, req->dr_items_nr,
1657  dix_item_get_has_failed(&req->dr_items[i]))) {
1660  } else if (req->dr_type == DIX_DEL && del_phase2) {
1661  m0_free(rop);
1662  req->dr_rop = rop_del_phase2;
1664  } else {
1666  }
1667 }
1668 
1669 static void dix_rop_one_completed(struct m0_dix_cas_rop *crop)
1670 {
1671  struct m0_dix_req *dreq = crop->crp_parent;
1672  struct m0_dix_rop_ctx *rop;
1673 
1674  M0_ENTRY();
1675  M0_PRE(!dreq->dr_is_meta);
1676  M0_PRE(M0_IN(dreq->dr_type, (DIX_PUT, DIX_DEL)));
1677  M0_PRE(dreq->dr_dtx != NULL);
1678  M0_PRE(dix_req_smgrp(dreq) == dreq->dr_dtx->tx_dtx->dd_sm.sm_grp);
1679 
1680  rop = crop->crp_parent->dr_rop;
1681  dix_cas_rop_rc_update(crop, 0);
1682 
1683  m0_dtx0_executed(dreq->dr_dtx, crop->crp_pa_idx);
1684 
1685  if (rop->dg_completed_nr == rop->dg_cas_reqs_nr) {
1686  rop->dg_ast = (struct m0_sm_ast) {
1688  .sa_datum = dreq,
1689  };
1690  m0_sm_ast_post(dix_req_smgrp(dreq), &rop->dg_ast);
1691  }
1692 
1693  M0_LEAVE();
1694 }
1695 
1696 static bool dix_cas_rop_clink_cb(struct m0_clink *cl)
1697 {
1698  struct m0_dix_cas_rop *crop = container_of(cl, struct m0_dix_cas_rop,
1699  crp_clink);
1700  uint32_t state = crop->crp_creq.ccr_sm.sm_state;
1701  struct m0_dix_rop_ctx *rop;
1702  struct m0_dix_req *dreq;
1703 
1704  if (M0_IN(state, (CASREQ_FINAL, CASREQ_FAILURE))) {
1705  dreq = crop->crp_parent;
1706 
1707  /*
1708  * Update pending transaction number. Note: as
1709  * m0_cas_req::ccr_fop is set to NULL in cas_req_reply_handle()
1710  * we must get the returned remid before that.
1711  */
1712  if (dreq->dr_cli->dx_sync_rec_update != NULL)
1713  dreq->dr_cli->dx_sync_rec_update(
1714  dreq, crop->crp_creq.ccr_sess,
1715  &crop->crp_creq.ccr_remid);
1716 
1717 
1718  m0_clink_del(cl);
1719  m0_clink_fini(cl);
1720  rop = crop->crp_parent->dr_rop;
1721  rop->dg_completed_nr++;
1722  M0_PRE(rop->dg_completed_nr <= rop->dg_cas_reqs_nr);
1723 
1724  if (dreq->dr_dtx != NULL) {
1725  M0_ASSERT(dix_req_smgrp(dreq) ==
1726  dreq->dr_dtx->tx_dtx->dd_sm.sm_grp);
1727  dix_rop_one_completed(crop);
1728  } else {
1729  if (rop->dg_completed_nr == rop->dg_cas_reqs_nr) {
1730  rop->dg_ast = (struct m0_sm_ast) {
1732  .sa_datum = dreq,
1733  };
1735  &rop->dg_ast);
1736  }
1737  }
1738 
1739  }
1740  return true;
1741 }
1742 
1743 static int dix_cas_rops_send(struct m0_dix_req *req)
1744 {
1745  struct m0_pools_common *pc = req->dr_cli->dx_pc;
1746  struct m0_dix_rop_ctx *rop = req->dr_rop;
1747  struct m0_dix_cas_rop *cas_rop;
1748  struct m0_cas_req *creq;
1749  uint32_t sdev_idx;
1750  uint32_t pa_idx;
1751  struct m0_cas_id cctg_id;
1752  struct m0_reqh_service_ctx *cas_svc;
1753  struct m0_dix_layout *layout = &req->dr_indices[0].dd_layout;
1754  int rc;
1755  M0_ENTRY("req=%p", req);
1756 
1757  M0_PRE(rop->dg_cas_reqs_nr == 0);
1758  m0_tl_for(cas_rop, &rop->dg_cas_reqs, cas_rop) {
1759  sdev_idx = cas_rop->crp_sdev_idx;
1760  creq = &cas_rop->crp_creq;
1761  cas_svc = pc->pc_dev2svc[sdev_idx].pds_ctx;
1762  M0_ASSERT(cas_svc->sc_type == M0_CST_CAS);
1763  m0_cas_req_init(creq, &cas_svc->sc_rlink.rlk_sess,
1764  dix_req_smgrp(req));
1765  dix_to_cas_map(req, creq);
1767  m0_clink_add(&creq->ccr_sm.sm_chan, &cas_rop->crp_clink);
1768  M0_ASSERT(req->dr_indices_nr == 1);
1769  m0_dix_fid_convert_dix2cctg(&req->dr_indices[0].dd_fid,
1770  &cctg_id.ci_fid, sdev_idx);
1771  M0_ASSERT(layout->dl_type == DIX_LTYPE_DESCR);
1772  cctg_id.ci_layout.dl_type = layout->dl_type;
1773  rc = m0_dix_ldesc_copy(&cctg_id.ci_layout.u.dl_desc,
1774  &layout->u.dl_desc);
1775  if (rc == 0) {
1776  M0_LOG(M0_DEBUG, "Processing dix_req %p[%u] "FID_F
1777  " creq=%p "FID_F,
1778  req, req->dr_type,
1779  FID_P(&req->dr_indices[0].dd_fid),
1780  creq, FID_P(&cctg_id.ci_fid));
1781 
1782  switch (req->dr_type) {
1783  case DIX_GET:
1784  rc = m0_cas_get(creq, &cctg_id,
1785  &cas_rop->crp_keys);
1786  break;
1787  case DIX_PUT:
1788  rc = m0_cas_put(creq, &cctg_id,
1789  &cas_rop->crp_keys,
1790  &cas_rop->crp_vals,
1791  req->dr_dtx,
1792  cas_rop->crp_flags);
1793  break;
1794  case DIX_DEL:
1795  rc = m0_cas_del(creq, &cctg_id,
1796  &cas_rop->crp_keys,
1797  req->dr_dtx,
1798  cas_rop->crp_flags);
1799  break;
1800  case DIX_NEXT:
1801  rc = m0_cas_next(creq, &cctg_id,
1802  &cas_rop->crp_keys,
1803  req->dr_recs_nr,
1804  cas_rop->crp_flags |
1805  COF_SLANT);
1806  break;
1807  default:
1808  M0_IMPOSSIBLE("Unknown req type %u",
1809  req->dr_type);
1810  }
1811  m0_cas_id_fini(&cctg_id);
1812  }
1813 
1814  if (rc != 0) {
1815  /*
1816  * Treat failed and not sent CAS requests as executed
1817  * to unblock the EXECUTED-ALL logic. It allows to move
1818  * transaction to the stable state once the persistent
1819  * message received (EXECUTED state required for all
1820  * participants). So EXECUTED participant state is
1821  * reused in case of failure.
1822  */
1823  if (req->dr_dtx != NULL)
1824  m0_dtx0_executed(req->dr_dtx,
1825  cas_rop->crp_pa_idx);
1826  m0_clink_del(&cas_rop->crp_clink);
1827  m0_clink_fini(&cas_rop->crp_clink);
1828  m0_cas_req_fini(&cas_rop->crp_creq);
1829  dix_cas_rop_rc_update(cas_rop, rc);
1830  cas_rop_tlink_del_fini(cas_rop);
1831  dix_cas_rop_fini(cas_rop);
1832  m0_free(cas_rop);
1833  } else {
1834  if (req->dr_dtx != NULL) {
1835  m0_dtx0_fop_assign(req->dr_dtx,
1836  cas_rop->crp_pa_idx,
1837  creq->ccr_fop);
1838  }
1839  rop->dg_cas_reqs_nr++;
1840  }
1841  } m0_tl_endfor;
1842 
1843  M0_LOG(M0_DEBUG, "Processing dix_req %p rop=%p: dg_cas_reqs_nr=%"PRIu64,
1844  req, rop, rop->dg_cas_reqs_nr);
1845  if (rop->dg_cas_reqs_nr == 0)
1846  return M0_ERR(-EFAULT);
1847 
1848  if (req->dr_dtx != NULL) {
1849  rc = m0_dtx0_close(req->dr_dtx);
1850  if (rc != 0)
1851  return M0_ERR(rc);
1852  /*
1853  * It is safe to set EXECUTED dtx state for those
1854  * participants that experience transient failure,
1855  * it allows to trigger EXECUTED-ALL logic. See
1856  * the similar comment above for details.
1857  */
1858  for (pa_idx = cas_rop_tlist_length(&rop->dg_cas_reqs);
1859  pa_idx < req->dr_dtx->tx_dtx->dd_txd.dtd_ps.dtp_nr;
1860  pa_idx++)
1861  m0_dtx0_executed(req->dr_dtx, pa_idx);
1862  }
1863 
1864  return M0_RC(0);
1865 }
1866 
1867 static void dix_rop_tgt_iter_begin(const struct m0_dix_req *req,
1868  struct m0_dix_rec_op *rec_op)
1869 {
1870  if (req->dr_type == DIX_NEXT)
1871  rec_op->dgp_next_tgt = 0;
1872  else
1874 }
1875 
1876 static uint32_t dix_rop_tgt_iter_max(struct m0_dix_req *req,
1877  struct m0_dix_rec_op *rec_op)
1878 {
1879  struct m0_dix_layout_iter *iter = &rec_op->dgp_iter;
1880  enum dix_req_type type = req->dr_type;
1881 
1882  M0_ASSERT(M0_IN(type, (DIX_GET, DIX_PUT, DIX_DEL, DIX_NEXT)));
1883  if (type == DIX_NEXT)
1884  /*
1885  * NEXT operation should be sent to all devices, because the
1886  * distribution of keys over devices is unknown. Therefore, all
1887  * component catalogues should be queried and returned records
1888  * should be merge-sorted.
1889  */
1890  return m0_dix_liter_P(iter);
1891  else
1892  /* Skip spares when DTM0 is enabled */
1893  return ENABLE_DTM0 ?
1894  m0_dix_liter_N(iter) + m0_dix_liter_K(iter) :
1895  m0_dix_liter_N(iter) +
1896  m0_dix_liter_K(iter) +
1897  m0_dix_liter_S(iter);
1898 }
1899 
1900 static void dix_rop_tgt_iter_next(const struct m0_dix_req *req,
1901  struct m0_dix_rec_op *rec_op,
1902  uint64_t *target,
1903  bool *is_spare)
1904 {
1905  if (req->dr_type != DIX_NEXT) {
1907  rec_op->dgp_iter.dit_unit) == M0_PUT_SPARE;
1908  m0_dix_layout_iter_next(&rec_op->dgp_iter, target);
1909  } else {
1910  *target = rec_op->dgp_next_tgt++;
1911  *is_spare = false;
1912  }
1913 }
1914 
1915 static int dix_spare_slot_find(struct m0_poolmach_state *pm_state,
1916  uint64_t failed_tgt,
1917  uint32_t *spare_slot)
1918 {
1919  struct m0_pool_spare_usage *spare_usage_array;
1920  uint32_t i;
1921 
1922  spare_usage_array = pm_state->pst_spare_usage_array;
1923  for (i = 0; i < pm_state->pst_nr_spares; i++) {
1924  if (spare_usage_array[i].psu_device_index == failed_tgt) {
1925  *spare_slot = i;
1926  return 0;
1927  }
1928  }
1929  return M0_ERR_INFO(-ENOENT, "No spare slot found for target %"PRIu64,
1930  failed_tgt);
1931 }
1932 
1933 static struct m0_pool_version *dix_rec_op_pver(struct m0_dix_rec_op *rec_op)
1934 {
1935  return m0_pdl_to_layout(rec_op->dgp_iter.dit_linst.li_pl)->l_pver;
1936 }
1937 
1938 static uint32_t dix_rop_max_failures(struct m0_dix_rop_ctx *rop)
1939 {
1940  struct m0_pool_version *pver = rop->dg_pver;
1941 
1942  M0_ASSERT(pver != NULL);
1943  return pver->pv_mach.pm_state->pst_max_device_failures;
1944 }
1945 
1946 static uint32_t dix_rec_op_spare_offset(struct m0_dix_rec_op *rec_op)
1947 {
1948  return m0_dix_liter_spare_offset(&rec_op->dgp_iter);
1949 }
1950 
1951 static int dix__spare_target(struct m0_dix_rec_op *rec_op,
1952  const struct m0_dix_pg_unit *failed_unit,
1953  uint32_t *spare_slot,
1954  struct m0_dix_pg_unit **spare_unit,
1955  bool with_data)
1956 {
1957  struct m0_pool_version *pver;
1958  struct m0_poolmach_state *pm_state;
1959  struct m0_dix_pg_unit *spare;
1960  uint32_t slot;
1961  uint64_t spare_offset;
1962  uint64_t tgt;
1963  int rc;
1964 
1965  /*
1966  * Pool machine should be locked here. It is done in
1967  * dix_rop_units_set().
1968  */
1969  pver = dix_rec_op_pver(rec_op);
1970  pm_state = pver->pv_mach.pm_state;
1971  spare_offset = dix_rec_op_spare_offset(rec_op);
1972  M0_PRE(ergo(with_data, M0_IN(failed_unit->dpu_pd_state,
1974  tgt = failed_unit->dpu_tgt;
1975  do {
1976  rc = dix_spare_slot_find(pm_state, tgt, &slot);
1977  if (rc != 0)
1978  return M0_ERR(rc);
1979  spare = &rec_op->dgp_units[spare_offset + slot];
1980  if (!spare->dpu_unavail) {
1981  /* Found an available spare unit, exit the loop. */
1982  *spare_unit = spare;
1983  *spare_slot = slot;
1984  return M0_RC(0);
1985  }
1986  if (with_data && M0_IN(spare->dpu_pd_state,
1988  /*
1989  * Spare unit with repaired data is requested, but some
1990  * spare unit in a chain is not repaired yet.
1991  */
1992  return M0_ERR(-ENODEV);
1993  }
1994  tgt = spare->dpu_tgt;
1995  } while (1);
1996 }
1997 
1998 static int dix_spare_target(struct m0_dix_rec_op *rec_op,
1999  const struct m0_dix_pg_unit *failed_unit,
2000  uint32_t *spare_slot,
2001  struct m0_dix_pg_unit **spare_unit)
2002 {
2003  return dix__spare_target(rec_op, failed_unit, spare_slot, spare_unit,
2004  false);
2005 }
2006 
2007 static int dix_spare_target_with_data(struct m0_dix_rec_op *rec_op,
2008  const struct m0_dix_pg_unit *failed_unit,
2009  uint32_t *spare_slot,
2010  struct m0_dix_pg_unit **spare_unit)
2011 {
2012  return dix__spare_target(rec_op, failed_unit, spare_slot, spare_unit,
2013  true);
2014 }
2015 
2017  struct m0_dix_rec_op *rec_op)
2018 {
2019  struct m0_dix_pg_unit *pgu;
2020  uint64_t start_unit;
2021  uint64_t i;
2022  uint64_t j;
2023 
2024  M0_ENTRY();
2025  M0_PRE(req->dr_type == DIX_GET);
2026  start_unit = req->dr_items[rec_op->dgp_item].dxi_pg_unit;
2027  M0_ASSERT(start_unit < dix_rec_op_spare_offset(rec_op));
2028  for (i = 0; i < start_unit; i++)
2029  rec_op->dgp_units[i].dpu_unavail = true;
2030  for (i = start_unit; i < rec_op->dgp_units_nr; i++) {
2031  pgu = &rec_op->dgp_units[i];
2032  if (!pgu->dpu_is_spare && !pgu->dpu_unavail)
2033  break;
2034  }
2035  for (j = i + 1; j < rec_op->dgp_units_nr; j++)
2036  rec_op->dgp_units[j].dpu_unavail = true;
2037 }
2038 
2039 static void dix_pg_unit_pd_assign(struct m0_dix_pg_unit *pgu,
2040  struct m0_pooldev *pd)
2041 {
2042  pgu->dpu_tgt = pd->pd_index;
2043  pgu->dpu_sdev_idx = pd->pd_sdev_idx;
2044  pgu->dpu_pd_state = pd->pd_state;
2045  pgu->dpu_unavail = pool_failed_devs_tlink_is_in(pd) ||
2046  pgu->dpu_pd_state == M0_PNDS_OFFLINE;
2047 }
2048 
2056  struct m0_dix_rec_op *rec_op,
2057  uint64_t unit)
2058 {
2059  struct m0_dix_pg_unit *pgu = &rec_op->dgp_units[unit];
2060  struct m0_dix_pg_unit *spare;
2061  uint32_t spare_offset;
2062  uint32_t spare_slot;
2063  int rc;
2064 
2065  M0_ENTRY();
2067  M0_PRE(pgu->dpu_unavail);
2068  M0_PRE(M0_IN(pgu->dpu_pd_state, (M0_PNDS_FAILED,
2072  switch (req->dr_type) {
2073  case DIX_NEXT:
2074  /* Do nothing. */
2075  break;
2076  case DIX_GET:
2077  if (M0_IN(pgu->dpu_pd_state, (M0_PNDS_SNS_REPAIRED,
2079  rc = dix_spare_target_with_data(rec_op, pgu,
2080  &spare_slot, &spare);
2081  if (rc == 0) {
2082  spare->dpu_is_spare = false;
2083  break;
2084  }
2085  }
2086  break;
2087  case DIX_PUT:
2089  pgu->dpu_unavail = false;
2090  rc = dix_spare_target(rec_op, pgu, &spare_slot, &spare);
2091  if (rc == 0) {
2092  spare_offset = dix_rec_op_spare_offset(rec_op);
2093  unit = spare_offset + spare_slot;
2094  rec_op->dgp_units[unit].dpu_is_spare = false;
2095  }
2096  break;
2097  case DIX_DEL:
2098  if (pgu->dpu_pd_state == M0_PNDS_FAILED)
2099  break;
2100  rc = dix_spare_target(rec_op, pgu, &spare_slot, &spare);
2101  if (rc != 0)
2102  break;
2103  spare_offset = dix_rec_op_spare_offset(rec_op);
2104  unit = spare_offset + spare_slot;
2105  if (pgu->dpu_pd_state == M0_PNDS_SNS_REPAIRED) {
2106  rec_op->dgp_units[unit].dpu_is_spare = false;
2107  } else if (pgu->dpu_pd_state == M0_PNDS_SNS_REPAIRING) {
2108  rec_op->dgp_units[unit].dpu_del_phase2 = true;
2109  } else if (pgu->dpu_pd_state == M0_PNDS_SNS_REBALANCING) {
2110  rec_op->dgp_units[unit].dpu_is_spare = false;
2111  pgu->dpu_del_phase2 = true;
2112  }
2113  break;
2114  default:
2115  M0_IMPOSSIBLE("Invalid request type %d", req->dr_type);
2116  }
2117  M0_LEAVE();
2118 }
2119 
2129 {
2130  struct m0_dix_rop_ctx *rop = req->dr_rop;
2131  struct m0_dix_rec_op *rec_op;
2132  struct m0_dix_pg_unit *unit;
2133  uint32_t i;
2134  uint32_t j;
2135 
2136  for (i = 0; i < rop->dg_rec_ops_nr; i++) {
2137  rec_op = &rop->dg_rec_ops[i];
2138  for (j = 0; j < rec_op->dgp_units_nr; j++) {
2139  unit = &rec_op->dgp_units[j];
2140  if (!unit->dpu_is_spare && unit->dpu_unavail) {
2141  rec_op->dgp_failed_devs_nr++;
2142  dix_rop_failed_unit_tgt(req, rec_op, j);
2143  }
2144  }
2145  }
2146 }
2147 
2148 static void dix_rop_units_set(struct m0_dix_req *req)
2149 {
2150  struct m0_dix_rop_ctx *rop = req->dr_rop;
2151  struct m0_dix_rec_op *rec_op;
2152  struct m0_dix_pg_unit *unit;
2153  struct m0_pooldev *pd;
2154  struct m0_poolmach *pm = &rop->dg_pver->pv_mach;
2155  struct m0_pool *pool = rop->dg_pver->pv_pool;
2156  uint64_t tgt;
2157  uint32_t i;
2158  uint32_t j;
2159 
2161 
2162  /*
2163  * Determine destination devices for all records for all units as it
2164  * should be without failures in a pool.
2165  */
2166  for (i = 0; i < rop->dg_rec_ops_nr; i++) {
2167  rec_op = &rop->dg_rec_ops[i];
2168  dix_rop_tgt_iter_begin(req, rec_op);
2169  for (j = 0; j < rec_op->dgp_units_nr; j++) {
2170  unit = &rec_op->dgp_units[j];
2171  dix_rop_tgt_iter_next(req, rec_op, &tgt,
2172  &unit->dpu_is_spare);
2174  "We do not operate with spares in DTM0");
2175  pd = m0_dix_tgt2sdev(&rec_op->dgp_iter.dit_linst, tgt);
2176  dix_pg_unit_pd_assign(unit, pd);
2177  }
2178  }
2179 
2180  /*
2181  * Analyse failures in a pool and modify individual units state
2182  * in order to send CAS requests to proper destinations. Hold pool
2183  * machine lock to get consistent results.
2184  */
2185  if (pm->pm_pver->pv_is_dirty &&
2186  !pool_failed_devs_tlist_is_empty(&pool->po_failed_devices)) {
2187  if (ENABLE_DTM0)
2188  M0_IMPOSSIBLE("DTM0 can not operate when permanently"
2189  " failed devices exist.");
2190 
2192  }
2193 
2195 
2196  /*
2197  * Only one CAS GET request should be sent for every record.
2198  * Choose the best destination for every record.
2199  */
2200  if (req->dr_type == DIX_GET) {
2201  for (i = 0; i < rop->dg_rec_ops_nr; i++)
2203  }
2204 }
2205 
2206 static bool dix_pg_unit_skip(struct m0_dix_req *req,
2207  struct m0_dix_pg_unit *unit)
2208 {
2210  return unit->dpu_unavail || unit->dpu_is_spare;
2211  else
2212  return !unit->dpu_del_phase2;
2213 }
2214 
2215 static int dix_cas_rops_alloc(struct m0_dix_req *req)
2216 {
2217  struct m0_dix_rop_ctx *rop = req->dr_rop;
2218  struct m0_dtx *dtx = req->dr_dtx;
2219  struct m0_pools_common *pc = req->dr_cli->dx_pc;
2220  struct m0_reqh_service_ctx *cas_svc;
2221  struct m0_dix_rec_op *rec_op;
2222  uint32_t i;
2223  uint32_t j;
2224  uint32_t pa_idx = 0;
2225  uint32_t pa_nr = 0;
2226  uint32_t max_failures;
2227  struct m0_dix_cas_rop **map = rop->dg_target_rop;
2228  struct m0_dix_cas_rop *cas_rop;
2229  struct m0_dix_pg_unit *unit;
2230  bool del_lock;
2231  uint32_t *skipped_sdevs = NULL;
2232  uint32_t skipped_sdevs_num = 0;
2233  uint32_t skipped_sdevs_max =
2234  rop->dg_pver->pv_attr.pa_P;
2235  enum { INVALID_SDEV_ID = UINT32_MAX };
2236  int rc = 0;
2237 
2238  M0_ENTRY("req %p %u", req, rop->dg_rec_ops_nr);
2239  M0_ASSERT(rop->dg_rec_ops_nr > 0);
2240 
2241  if (dtx != NULL) {
2242  M0_ALLOC_ARR(skipped_sdevs, skipped_sdevs_max);
2243  if (skipped_sdevs == NULL)
2244  return M0_ERR(-ENOMEM);
2245  for (i = 0; i < skipped_sdevs_max; i++)
2246  skipped_sdevs[i] = INVALID_SDEV_ID;
2247  }
2248 
2249  max_failures = dix_rop_max_failures(rop);
2250  for (i = 0; i < rop->dg_rec_ops_nr; i++) {
2251  rec_op = &rop->dg_rec_ops[i];
2252  /*
2253  * If 2-phase delete is necessary, then CAS request should be
2254  * sent with COF_DEL_LOCK flag in order to prevent possible
2255  * concurrency issues with repair/re-balance process.
2256  */
2257  del_lock = (req->dr_type == DIX_DEL &&
2258  dix_del_phase2_is_needed(rec_op));
2259  if (rec_op->dgp_failed_devs_nr > max_failures) {
2260  req->dr_items[rec_op->dgp_item].dxi_rc = M0_ERR(-EIO);
2261  /* Skip this record operation. */
2262  continue;
2263  }
2264  for (j = 0; j < rec_op->dgp_units_nr; j++) {
2265  unit = &rec_op->dgp_units[j];
2266  if (dix_pg_unit_skip(req, unit)) {
2267  if (dtx != NULL &&
2268  unit->dpu_pd_state == M0_PNDS_OFFLINE &&
2269  skipped_sdevs[unit->dpu_tgt] ==
2270  INVALID_SDEV_ID) {
2271  skipped_sdevs[unit->dpu_tgt] =
2272  unit->dpu_sdev_idx;
2273  skipped_sdevs_num++;
2274  }
2275  continue;
2276  }
2277  if (map[unit->dpu_tgt] == NULL) {
2279  &cas_rop);
2280  if (rc != 0)
2281  goto end;
2282  map[unit->dpu_tgt] = cas_rop;
2283  }
2284  if (del_lock)
2285  map[unit->dpu_tgt]->crp_flags |= COF_DEL_LOCK;
2286  map[unit->dpu_tgt]->crp_keys_nr++;
2287  }
2288  }
2289 
2290  /* It is possible that all data units are not available. */
2291  if (cas_rop_tlist_is_empty(&rop->dg_cas_reqs)) {
2292  m0_free(skipped_sdevs);
2293  return M0_ERR(-EIO);
2294  }
2295 
2296  if (dtx != NULL) {
2297  M0_ASSERT(!req->dr_is_meta);
2298  M0_ASSERT(M0_IN(req->dr_type, (DIX_PUT, DIX_DEL)));
2299  pa_nr = cas_rop_tlist_length(&rop->dg_cas_reqs) +
2300  skipped_sdevs_num;
2301  rc = m0_dtx0_open(dtx, pa_nr);
2302  if (rc != 0)
2303  goto end;
2304  }
2305 
2306  pa_idx = 0;
2307  m0_tl_for(cas_rop, &rop->dg_cas_reqs, cas_rop) {
2308  if (dtx != NULL) {
2309  cas_rop->crp_pa_idx = pa_idx++;
2310  cas_svc = pc->pc_dev2svc[cas_rop->crp_sdev_idx].pds_ctx;
2311  M0_ASSERT(cas_svc->sc_type == M0_CST_CAS);
2312  rc = m0_dtx0_fid_assign(dtx, cas_rop->crp_pa_idx,
2313  &cas_svc->sc_fid);
2314  if (rc != 0)
2315  goto end;
2316  }
2317  M0_ALLOC_ARR(cas_rop->crp_attrs, cas_rop->crp_keys_nr);
2318  if (cas_rop->crp_attrs == NULL) {
2319  rc = M0_ERR(-ENOMEM);
2320  goto end;
2321  }
2322  rc = m0_bufvec_empty_alloc(&cas_rop->crp_keys,
2323  cas_rop->crp_keys_nr);
2324  if (rc != 0)
2325  goto end;
2326  if (req->dr_type == DIX_PUT) {
2327  rc = m0_bufvec_empty_alloc(&cas_rop->crp_vals,
2328  cas_rop->crp_keys_nr);
2329  if (rc != 0)
2330  goto end;
2331  }
2332  cas_rop->crp_cur_key = 0;
2333  } m0_tl_endfor;
2334 
2335  if (dtx == NULL)
2336  goto end;
2337 
2338  for (i = 0; i < skipped_sdevs_max && rc == 0; i++) {
2339  if (skipped_sdevs[i] != INVALID_SDEV_ID) {
2340  cas_svc = pc->pc_dev2svc[skipped_sdevs[i]].pds_ctx;
2341  M0_ASSERT(cas_svc->sc_type == M0_CST_CAS);
2342  M0_ASSERT(pa_idx < pa_nr);
2343  rc = m0_dtx0_fid_assign(dtx, pa_idx,
2344  &cas_svc->sc_fid);
2345  pa_idx++;
2346  }
2347  }
2348 end:
2349  m0_free(skipped_sdevs);
2350  if (rc != 0) {
2352  return M0_ERR(rc);
2353  }
2354  return M0_RC(0);
2355 }
2356 
2357 static int dix_cas_rops_fill(struct m0_dix_req *req)
2358 {
2359  struct m0_dix_rop_ctx *rop = req->dr_rop;
2360  struct m0_dix_cas_rop **map = rop->dg_target_rop;
2361  struct m0_dix_rec_op *rec_op;
2362  uint32_t j;
2363  uint32_t i;
2364  uint64_t tgt;
2365  uint64_t item;
2366  struct m0_bufvec *keys;
2367  struct m0_bufvec *vals;
2368  struct m0_buf *key;
2369  uint32_t idx;
2370  struct m0_dix_pg_unit *unit;
2371 
2372  M0_ENTRY("req %p", req);
2373  for (i = 0; i < rop->dg_rec_ops_nr; i++) {
2374  rec_op = &rop->dg_rec_ops[i];
2375  item = rec_op->dgp_item;
2376  for (j = 0; j < rec_op->dgp_units_nr; j++) {
2377  unit = &rec_op->dgp_units[j];
2378  tgt = unit->dpu_tgt;
2379  if (dix_pg_unit_skip(req, unit))
2380  continue;
2381  M0_ASSERT(map[tgt] != NULL);
2382  keys = &map[tgt]->crp_keys;
2383  vals = &map[tgt]->crp_vals;
2384  key = &rec_op->dgp_key;
2385  idx = map[tgt]->crp_cur_key;
2386  keys->ov_vec.v_count[idx] = key->b_nob;
2387  keys->ov_buf[idx] = key->b_addr;
2388  if (req->dr_type == DIX_PUT) {
2389  vals->ov_vec.v_count[idx] =
2390  req->dr_vals->ov_vec.v_count[item];
2391  vals->ov_buf[idx] =
2392  req->dr_vals->ov_buf[item];
2393  }
2394  map[tgt]->crp_attrs[idx].cra_item = item;
2395  map[tgt]->crp_cur_key++;
2396  }
2397  }
2398  return M0_RC(0);
2399 }
2400 
2401 M0_INTERNAL int m0_dix_put(struct m0_dix_req *req,
2402  const struct m0_dix *index,
2403  const struct m0_bufvec *keys,
2404  const struct m0_bufvec *vals,
2405  struct m0_dtx *dtx,
2406  uint32_t flags)
2407 {
2408  uint32_t keys_nr = keys->ov_vec.v_nr;
2409  int rc;
2410 
2411  M0_PRE(keys->ov_vec.v_nr == vals->ov_vec.v_nr);
2412  M0_PRE(keys_nr != 0);
2413  /*
2414  * Only the following flags are allowed.
2415  */
2417  COF_SKIP_LAYOUT | COF_NO_DTM)) == 0);
2419  if (rc != 0)
2420  return M0_ERR(rc);
2421  M0_ALLOC_ARR(req->dr_items, keys_nr);
2422  if (req->dr_items == NULL)
2423  return M0_ERR(-ENOMEM);
2424  req->dr_items_nr = keys_nr;
2425  req->dr_keys = keys;
2426  req->dr_vals = vals;
2427  req->dr_dtx = dtx;
2428  req->dr_type = DIX_PUT;
2429  req->dr_flags = flags;
2430  dix_discovery(req);
2431  return M0_RC(0);
2432 }
2433 
2434 M0_INTERNAL int m0_dix_get(struct m0_dix_req *req,
2435  const struct m0_dix *index,
2436  const struct m0_bufvec *keys)
2437 {
2438  uint32_t keys_nr = keys->ov_vec.v_nr;
2439  int rc;
2440 
2441  M0_PRE(keys_nr != 0);
2443  if (rc != 0)
2444  return M0_ERR(rc);
2445  M0_ALLOC_ARR(req->dr_items, keys_nr);
2446  if (req->dr_items == NULL)
2447  return M0_ERR(-ENOMEM);
2448  req->dr_items_nr = keys_nr;
2449  req->dr_keys = keys;
2450  req->dr_type = DIX_GET;
2451  dix_discovery(req);
2452  return M0_RC(0);
2453 }
2454 
2455 M0_INTERNAL void m0_dix_get_rep(const struct m0_dix_req *req,
2456  uint64_t idx,
2457  struct m0_dix_get_reply *rep)
2458 {
2459  M0_PRE(m0_dix_generic_rc(req) == 0);
2460  M0_PRE(idx < req->dr_items_nr);
2461  rep->dgr_rc = req->dr_items[idx].dxi_rc;
2462  rep->dgr_val = req->dr_items[idx].dxi_val;
2463 }
2464 
2465 M0_INTERNAL int m0_dix_del(struct m0_dix_req *req,
2466  const struct m0_dix *index,
2467  const struct m0_bufvec *keys,
2468  struct m0_dtx *dtx,
2469  uint32_t flags)
2470 {
2471  uint32_t keys_nr = keys->ov_vec.v_nr;
2472  int rc;
2473 
2474  M0_PRE(keys_nr != 0);
2475  /* Only sync_wait flag is allowed. */
2476  M0_PRE((flags & ~(COF_SYNC_WAIT)) == 0);
2478  if (rc != 0)
2479  return M0_ERR(rc);
2480  M0_ALLOC_ARR(req->dr_items, keys_nr);
2481  if (req->dr_items == NULL)
2482  return M0_ERR(-ENOMEM);
2483  req->dr_items_nr = keys_nr;
2484  req->dr_keys = keys;
2485  req->dr_dtx = dtx;
2486  req->dr_type = DIX_DEL;
2487  req->dr_flags = flags;
2488  dix_discovery(req);
2489  return M0_RC(0);
2490 }
2491 
2492 M0_INTERNAL int m0_dix_next(struct m0_dix_req *req,
2493  const struct m0_dix *index,
2494  const struct m0_bufvec *start_keys,
2495  const uint32_t *recs_nr,
2496  uint32_t flags)
2497 {
2498  uint32_t keys_nr = start_keys->ov_vec.v_nr;
2499  uint32_t i;
2500  int rc;
2501 
2502  /* Only slant and exclude start key flags are allowed. */
2504  M0_PRE(keys_nr != 0);
2505 
2507  if (rc != 0)
2508  return M0_ERR(rc);
2509  M0_ALLOC_ARR(req->dr_items, keys_nr);
2510  M0_ALLOC_ARR(req->dr_recs_nr, keys_nr);
2511  if (req->dr_items == NULL || req->dr_recs_nr == NULL)
2512  /*
2513  * Memory will be deallocated in m0_dix_req_fini() if necessary.
2514  */
2515  return M0_ERR(-ENOMEM);
2516  req->dr_items_nr = keys_nr;
2517  req->dr_keys = start_keys;
2518  req->dr_type = DIX_NEXT;
2519  req->dr_flags = flags;
2520  for (i = 0; i < keys_nr; i++)
2521  req->dr_recs_nr[i] = recs_nr[i];
2522  dix_discovery(req);
2523  return 0;
2524 }
2525 
2526 M0_INTERNAL void m0_dix_next_rep(const struct m0_dix_req *req,
2527  uint64_t key_idx,
2528  uint64_t val_idx,
2529  struct m0_dix_next_reply *rep)
2530 {
2531  const struct m0_dix_next_resultset *rs = &req->dr_rs;
2532  struct m0_dix_next_results *res;
2533  struct m0_cas_next_reply **reps;
2534 
2535  M0_ASSERT(rs != NULL);
2536  M0_ASSERT(key_idx < rs->nrs_res_nr);
2537  res = &rs->nrs_res[key_idx];
2538  reps = res->drs_reps;
2539  M0_ASSERT(val_idx < res->drs_pos);
2540  M0_ASSERT(reps[val_idx]->cnp_rc == 0);
2541  rep->dnr_key = reps[val_idx]->cnp_key;
2542  rep->dnr_val = reps[val_idx]->cnp_val;
2543 }
2544 
2545 M0_INTERNAL uint32_t m0_dix_next_rep_nr(const struct m0_dix_req *req,
2546  uint64_t key_idx)
2547 {
2548  M0_ASSERT(key_idx < req->dr_rs.nrs_res_nr);
2549  return req->dr_rs.nrs_res[key_idx].drs_pos;
2550 }
2551 
2552 M0_INTERNAL int m0_dix_item_rc(const struct m0_dix_req *req,
2553  uint64_t idx)
2554 {
2555  M0_PRE(m0_dix_generic_rc(req) == 0);
2556  M0_PRE(idx < m0_dix_req_nr(req));
2557  return req->dr_items[idx].dxi_rc;
2558 }
2559 
2560 M0_INTERNAL int m0_dix_generic_rc(const struct m0_dix_req *req)
2561 {
2563  return M0_RC(req->dr_sm.sm_rc);
2564 }
2565 
2566 M0_INTERNAL int m0_dix_req_rc(const struct m0_dix_req *req)
2567 {
2568  int rc;
2569  int i;
2570 
2572  if (rc == 0)
2573  for (i = 0; i < m0_dix_req_nr(req); i++) {
2574  rc = m0_dix_item_rc(req, i);
2575  if (rc != 0)
2576  break;
2577  }
2578  return M0_RC(rc);
2579 }
2580 
2581 M0_INTERNAL uint64_t m0_dix_req_nr(const struct m0_dix_req *req)
2582 {
2583  return req->dr_items_nr;
2584 }
2585 
2586 M0_INTERNAL void m0_dix_get_rep_mlock(struct m0_dix_req *req, uint64_t idx)
2587 {
2589  M0_PRE(req->dr_type == DIX_GET);
2590  M0_PRE(idx < req->dr_items_nr);
2591 
2592  req->dr_items[idx].dxi_key = M0_BUF_INIT0;
2593  req->dr_items[idx].dxi_val = M0_BUF_INIT0;
2594 }
2595 
2596 M0_INTERNAL void m0_dix_next_rep_mlock(struct m0_dix_req *req,
2597  uint32_t key_idx,
2598  uint32_t val_idx)
2599 {
2600  struct m0_dix_next_resultset *rs = &req->dr_rs;
2601  struct m0_dix_next_results *res;
2602  struct m0_cas_next_reply **reps;
2603 
2605  M0_PRE(req->dr_type == DIX_NEXT);
2606  M0_PRE(rs != NULL);
2607  M0_PRE(key_idx < rs->nrs_res_nr);
2608  res = &rs->nrs_res[key_idx];
2609  reps = res->drs_reps;
2610  M0_PRE(val_idx < res->drs_pos);
2611  reps[val_idx]->cnp_val = M0_BUF_INIT0;
2612  reps[val_idx]->cnp_key = M0_BUF_INIT0;
2613 }
2614 
2615 static void dix_item_fini(const struct m0_dix_req *req,
2616  struct m0_dix_item *item)
2617 {
2618  switch(req->dr_type){
2619  case DIX_NEXT:
2620  m0_buf_free(&item->dxi_key);
2621  /* Fall through. */
2622  case DIX_GET:
2623  m0_buf_free(&item->dxi_val);
2624  break;
2625  default:
2626  break;
2627  }
2628 }
2629 
2630 M0_INTERNAL void m0_dix_req_fini(struct m0_dix_req *req)
2631 {
2632  uint32_t i;
2633 
2635  for (i = 0; i < req->dr_indices_nr; i++)
2636  m0_dix_fini(&req->dr_indices[i]);
2637  m0_free(req->dr_indices);
2638  M0_ASSERT((req->dr_orig_indices != NULL) ==
2639  (req->dr_type == DIX_CREATE));
2640  if (req->dr_orig_indices != NULL) {
2641  for (i = 0; i < req->dr_indices_nr; i++)
2642  m0_dix_fini(&req->dr_orig_indices[i]);
2643  m0_free(req->dr_orig_indices);
2644  }
2645  for (i = 0; i < req->dr_items_nr; i++)
2646  dix_item_fini(req, &req->dr_items[i]);
2647  m0_free(req->dr_items);
2648  m0_free(req->dr_recs_nr);
2649  m0_free(req->dr_rop);
2650  m0_dix_rs_fini(&req->dr_rs);
2651  m0_sm_fini(&req->dr_sm);
2652 }
2653 
2654 M0_INTERNAL void m0_dix_req_fini_lock(struct m0_dix_req *req)
2655 {
2656  struct m0_sm_group *grp = dix_req_smgrp(req);
2657 
2662 }
2663 
2664 M0_INTERNAL int m0_dix_copy(struct m0_dix *dst, const struct m0_dix *src)
2665 {
2666  *dst = *src;
2667  if (src->dd_layout.dl_type == DIX_LTYPE_DESCR)
2668  return m0_dix_ldesc_copy(&dst->dd_layout.u.dl_desc,
2669  &src->dd_layout.u.dl_desc);
2670  return 0;
2671 }
2672 
2673 M0_INTERNAL int m0_dix_desc_set(struct m0_dix *dix,
2674  const struct m0_dix_ldesc *desc)
2675 {
2677  return m0_dix_ldesc_copy(&dix->dd_layout.u.dl_desc, desc);
2678 }
2679 
2680 M0_INTERNAL void m0_dix_fini(struct m0_dix *dix)
2681 {
2682  if (dix->dd_layout.dl_type == DIX_LTYPE_DESCR)
2683  m0_dix_ldesc_fini(&dix->dd_layout.u.dl_desc);
2684 }
2685 
2686 M0_INTERNAL int m0_dix_sm_conf_init(void)
2687 {
2692 }
2693 
2694 M0_INTERNAL void m0_dix_sm_conf_fini(void)
2695 {
2698 }
2699 
2700 
2701 #undef M0_TRACE_SUBSYSTEM
2702 
2705 /*
2706  * Local variables:
2707  * c-indentation-style: "K&R"
2708  * c-basic-offset: 8
2709  * tab-width: 8
2710  * fill-column: 80
2711  * scroll-step: 1
2712  * End:
2713  */
2714 /*
2715  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
2716  */
M0_INTERNAL void m0_cas_req_fini(struct m0_cas_req *req)
Definition: client.c:291
struct m0_poolmach_state * pm_state
Definition: pool_machine.h:169
M0_INTERNAL int m0_dix_layout_put(struct m0_dix_meta_req *req, const struct m0_fid *fid, const struct m0_dix_layout *dlay, uint32_t nr, uint32_t flags)
Definition: meta.c:574
static m0_bindex_t indices[ZEROVEC_UT_SEGS_NR]
Definition: zerovec.c:38
static void dix_layout_find_ast_cb(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: req.c:285
struct m0_be_tx_remid ccr_remid
Definition: client.h:166
struct m0_dtm0_dtx * tx_dtx
Definition: dtm.h:563
M0_INTERNAL int m0_dix_layout_get(struct m0_dix_meta_req *req, const struct m0_fid *fid, uint32_t nr)
Definition: meta.c:626
#define M0_PRE(cond)
M0_INTERNAL void m0_sm_conf_init(struct m0_sm_conf *conf)
Definition: sm.c:340
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
struct m0_dix_layout dd_layout
Definition: req.h:112
Definition: dtm.h:554
M0_INTERNAL void m0_dix_get_rep(const struct m0_dix_req *req, uint64_t idx, struct m0_dix_get_reply *rep)
Definition: req.c:2455
M0_INTERNAL void m0_sm_fail(struct m0_sm *mach, int fail_state, int32_t rc)
Definition: sm.c:468
struct m0_dix_cli * dr_cli
Definition: req.h:192
struct m0_rpc_session * ccr_sess
Definition: client.h:130
static void dix_rop_del_phase2(struct m0_dix_req *req)
Definition: req.c:1586
static void dix_rop_failures_analyse(struct m0_dix_req *req)
Definition: req.c:2128
uint32_t dcd_idxop_reqs_nr
Definition: req_internal.h:81
struct m0_fid sc_fid
Definition: reqh_service.h:752
struct m0_dix_pg_unit * dgp_units
Definition: req_internal.h:153
M0_INTERNAL uint32_t m0_dix_liter_K(struct m0_dix_layout_iter *iter)
Definition: layout.c:280
int const char const void size_t int flags
Definition: dir.c:328
M0_INTERNAL int m0_dtx0_open(struct m0_dtx *dtx, uint32_t nr)
Definition: dtx.c:497
M0_INTERNAL int m0_sm_addb2_init(struct m0_sm_conf *conf, uint64_t id, uint64_t counter)
Definition: sm.c:846
struct m0_dix_req * ds_parent
Definition: req_internal.h:64
static int dix_idxop_reqs_send(struct m0_dix_req *req)
Definition: req.c:916
#define NULL
Definition: misc.h:38
uint32_t pst_nr_devices
Definition: pool_machine.h:108
static void dix_idxop_ctx_free(struct m0_dix_idxop_ctx *idxop)
Definition: req.c:480
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
Definition: req.h:179
uint32_t dr_flags
Definition: req.h:257
static struct m0_bufvec dst
Definition: xform.c:61
M0_INTERNAL void m0_clink_del(struct m0_clink *link)
Definition: chan.c:267
map
Definition: processor.c:112
struct m0_sm_ast dcd_ast
Definition: req_internal.h:84
M0_INTERNAL void m0_clink_del_lock(struct m0_clink *link)
Definition: chan.c:293
struct m0_pool_version * l_pver
Definition: layout.h:261
struct m0_dix_layout_iter dgp_iter
Definition: req_internal.h:142
static void addb2_add_dix_req_attrs(const struct m0_dix_req *req)
Definition: req.c:1080
#define ergo(a, b)
Definition: misc.h:293
void(* sa_cb)(struct m0_sm_group *grp, struct m0_sm_ast *)
Definition: sm.h:506
M0_INTERNAL int m0_dix_desc_set(struct m0_dix *dix, const struct m0_dix_ldesc *desc)
Definition: req.c:2673
static void dix_get_req_resend(struct m0_dix_req *req)
Definition: req.c:1463
Definition: sm.h:350
struct m0_pool_version * pm_pver
Definition: pool_machine.h:172
static int dix_idxop_meta_update(struct m0_dix_req *req)
Definition: req.c:839
M0_INTERNAL struct m0_pool_version * m0_pool_version_find(struct m0_pools_common *pc, const struct m0_fid *id)
Definition: pool.c:586
static void dix_cas_rops_fini(struct m0_tl *cas_rops)
Definition: req.c:1292
static struct io_request req
Definition: file.c:100
static struct m0_sm_group * grp
Definition: bytecount.c:38
#define m0_count(var, nr,...)
Definition: misc.h:79
uint64_t m0_time_t
Definition: time.h:37
struct m0_poolmach pv_mach
Definition: pool.h:133
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
dix_layout_type
Definition: layout.h:62
M0_INTERNAL void m0_sm_ast_post(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: sm.c:135
static int dix_id_layouts_nr(struct m0_dix_req *req)
Definition: req.c:267
static void dix_rop_one_completed(struct m0_dix_cas_rop *crop)
Definition: req.c:1669
struct m0_clink ds_clink
Definition: req_internal.h:66
static bool dix_req_is_idxop(const struct m0_dix_req *req)
Definition: req.c:165
struct m0_dix_linst dit_linst
Definition: layout.h:135
M0_INTERNAL int m0_dix_ldescr_rep_get(struct m0_dix_meta_req *req, uint64_t idx, struct m0_dix_ldesc *ldesc)
Definition: meta.c:530
static void create(void)
Definition: service_ut.c:547
M0_INTERNAL int m0_dix_next_result_prepare(struct m0_dix_req *req)
Definition: next_merge.c:252
Definition: cas.h:247
struct m0_vec ov_vec
Definition: vec.h:147
static enum m0_dix_req_state dix_req_state(const struct m0_dix_req *req)
Definition: req.c:235
M0_INTERNAL void m0_dix_mreq_init(struct m0_dix_req *req, struct m0_dix_cli *cli, struct m0_sm_group *grp)
Definition: req.c:221
M0_INTERNAL int m0_dix_delete(struct m0_dix_req *req, const struct m0_dix *indices, uint64_t indices_nr, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:1190
M0_INTERNAL void m0_dix_meta_req_init(struct m0_dix_meta_req *req, struct m0_dix_cli *cli, struct m0_sm_group *grp)
Definition: meta.c:259
void m0_dix_req_cancel(struct m0_dix_req *dreq)
Definition: req.c:1152
static void dix_layout_find(struct m0_dix_req *req)
Definition: req.c:383
M0_INTERNAL void m0_cas_id_fini(struct m0_cas_id *cid)
Definition: cas.c:199
M0_INTERNAL int m0_dix_req_rc(const struct m0_dix_req *req)
Definition: req.c:2566
dix_req_type
Definition: req.h:171
M0_INTERNAL void m0_cas_get_rep(const struct m0_cas_req *req, uint64_t idx, struct m0_cas_get_reply *rep)
Definition: client.c:1764
struct m0_dix_cas_req * dcr_creqs
Definition: req_internal.h:74
M0_INTERNAL int m0_dix_item_rc(const struct m0_dix_req *req, uint64_t idx)
Definition: req.c:2552
M0_INTERNAL int m0_dtx0_close(struct m0_dtx *dtx)
Definition: dtx.c:520
struct m0_dix_rop_ctx * dr_rop
Definition: req.h:244
struct m0_dix_layout ci_layout
Definition: cas.h:120
M0_INTERNAL int m0_dix_layout_iter_init(struct m0_dix_layout_iter *iter, const struct m0_fid *index, struct m0_layout_domain *ldom, struct m0_pool_version *pver, struct m0_dix_ldesc *ldesc, struct m0_buf *key)
Definition: layout.c:203
static struct m0_sm_group * dix_req_smgrp(const struct m0_dix_req *req)
Definition: req.c:170
uint32_t dgp_failed_devs_nr
Definition: req_internal.h:159
M0_INTERNAL const char * m0_sm_state_name(const struct m0_sm *mach, int state)
Definition: sm.c:781
M0_INTERNAL void m0_cas_index_create_rep(const struct m0_cas_req *req, uint64_t idx, struct m0_cas_rec_reply *rep)
Definition: client.c:1360
#define m0_exists(var, nr,...)
Definition: misc.h:134
uint32_t dpu_tgt
Definition: req_internal.h:124
#define M0_BITS(...)
Definition: misc.h:236
static bool is_spare(uint64_t alloc_flags)
Definition: balloc.c:1049
struct m0_pool_version * dcr_pver
Definition: req_internal.h:73
Definition: sm.h:504
static bool dix_item_should_be_sent(const struct m0_dix_req *req, uint32_t i)
Definition: req.c:909
#define container_of(ptr, type, member)
Definition: misc.h:33
static void dix_idxop_meta_update_ast_cb(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: req.c:767
#define M0_SET0(obj)
Definition: misc.h:64
M0_ADDB2_ADD(M0_AVI_FS_CREATE, new_fid.f_container, new_fid.f_key, mode, rc)
struct m0_dix_req dmr_req
Definition: meta.h:94
M0_INTERNAL bool m0_sm_addb2_counter_init(struct m0_sm *sm)
Definition: sm.c:891
void(* dx_sync_rec_update)(struct m0_dix_req *, struct m0_rpc_session *, struct m0_be_tx_remid *)
Definition: client.h:202
struct m0_pool * pv_pool
Definition: pool.h:128
bool pv_is_dirty
Definition: pool.h:116
static struct m0_rpc_item * item
Definition: item.c:56
struct m0_fop_getxattr_rep * rep
Definition: dir.c:455
M0_INTERNAL void m0_dix_rs_fini(struct m0_dix_next_resultset *rs)
Definition: next_merge.c:356
void ** ov_buf
Definition: vec.h:149
#define UINT32_MAX
Definition: types.h:41
M0_INTERNAL int m0_cas_get(struct m0_cas_req *req, struct m0_cas_id *index, const struct m0_bufvec *keys)
Definition: client.c:1750
M0_INTERNAL void m0_dix_req_fini(struct m0_dix_req *req)
Definition: req.c:2630
M0_INTERNAL uint32_t m0_dix_liter_S(struct m0_dix_layout_iter *iter)
Definition: layout.c:285
static struct m0_pools_common pc
Definition: iter_ut.c:59
struct m0_buf cnp_val
Definition: client.h:223
M0_INTERNAL int m0_dix_copy(struct m0_dix *dst, const struct m0_dix *src)
Definition: req.c:2664
M0_INTERNAL void m0_dix_layout_iter_fini(struct m0_dix_layout_iter *iter)
Definition: layout.c:315
M0_INTERNAL int m0_dix_ldesc_copy(struct m0_dix_ldesc *dst, const struct m0_dix_ldesc *src)
Definition: layout.c:189
struct m0_sm dd_sm
Definition: dtx.h:61
#define m0_tl_endfor
Definition: tlist.h:700
M0_INTERNAL int m0_sm_timedwait(struct m0_sm *mach, uint64_t states, m0_time_t deadline)
Definition: sm.c:387
struct m0_pooldev * pst_devices_array
Definition: pool_machine.h:111
struct m0_cas_req crp_creq
Definition: req_internal.h:94
static void dix_rop_tgt_iter_next(const struct m0_dix_req *req, struct m0_dix_rec_op *rec_op, uint64_t *target, bool *is_spare)
Definition: req.c:1900
return M0_RC(rc)
struct m0_buf dxi_val
Definition: req_internal.h:48
static bool dix_layout_find_clink_cb(struct m0_clink *cl)
Definition: req.c:371
M0_INTERNAL uint64_t m0_dix_req_nr(const struct m0_dix_req *req)
Definition: req.c:2581
struct m0_sm ccr_sm
Definition: client.h:125
#define M0_ENTRY(...)
Definition: trace.h:170
Definition: buf.h:37
static uint32_t dix_rop_tgt_iter_max(struct m0_dix_req *req, struct m0_dix_rec_op *rec_op)
Definition: req.c:1876
static struct m0_sm_ast ast[NR]
Definition: locality.c:44
M0_INTERNAL void m0_sm_group_unlock(struct m0_sm_group *grp)
Definition: sm.c:96
static struct m0_pool_version * dix_rec_op_pver(struct m0_dix_rec_op *rec_op)
Definition: req.c:1933
uint32_t dpu_sdev_idx
Definition: req_internal.h:127
static bool dix_idxop_clink_cb(struct m0_clink *cl)
Definition: req.c:568
int i
Definition: dir.c:1033
#define M0_RC_INFO(rc, fmt,...)
Definition: trace.h:209
static uint32_t dix_rop_max_failures(struct m0_dix_rop_ctx *rop)
Definition: req.c:1938
#define PRIu64
Definition: types.h:58
static bool dix_item_get_has_failed(struct m0_dix_item *item)
Definition: req.c:1449
M0_INTERNAL int m0_dix_layout_rep_get(struct m0_dix_meta_req *req, uint64_t idx, struct m0_dix_layout *dlay)
Definition: meta.c:650
M0_INTERNAL int m0_dix_next(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *start_keys, const uint32_t *recs_nr, uint32_t flags)
Definition: req.c:2492
bool dr_is_meta
Definition: req.h:222
uint32_t pst_nr_spares
Definition: pool_machine.h:120
#define M0_ERR_INFO(rc, fmt,...)
Definition: trace.h:215
return M0_ERR(-EOPNOTSUPP)
void * sa_datum
Definition: sm.h:508
M0_INTERNAL int m0_cas_req_generic_rc(const struct m0_cas_req *req)
Definition: client.c:460
M0_INTERNAL void m0_cas_req_init(struct m0_cas_req *req, struct m0_rpc_session *sess, struct m0_sm_group *grp)
Definition: client.c:198
uint64_t dcd_completed_nr
Definition: req_internal.h:83
static int key
Definition: locality.c:283
struct m0_sm dr_sm
Definition: req.h:190
void m0_rpc_item_cancel(struct m0_rpc_item *item)
Definition: item.c:932
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
static void dix_online_unit_choose(struct m0_dix_req *req, struct m0_dix_rec_op *rec_op)
Definition: req.c:2016
uint32_t dg_rec_ops_nr
Definition: req_internal.h:164
#define m0_tl_teardown(name, head, obj)
Definition: tlist.h:708
M0_INTERNAL void m0_cas_put_rep(struct m0_cas_req *req, uint64_t idx, struct m0_cas_rec_reply *rep)
Definition: client.c:1694
Definition: cas.h:264
uint64_t dcr_creqs_nr
Definition: req_internal.h:75
#define ENABLE_DTM0
Definition: config.h:36
static void dix_req_state_set(struct m0_dix_req *req, enum m0_dix_req_state state)
Definition: req.c:240
M0_INTERNAL int m0_cas_next(struct m0_cas_req *req, struct m0_cas_id *index, struct m0_bufvec *start_keys, uint32_t *recs_nr, uint32_t flags)
Definition: client.c:1784
struct m0_fid dd_fid
Definition: req.h:111
#define m0_free0(pptr)
Definition: memory.h:77
#define M0_ASSERT(cond)
const char * scf_name
Definition: sm.h:352
static void dix_item_rc_update(struct m0_dix_req *req, struct m0_cas_req *creq, uint64_t key_idx, struct m0_dix_item *ditem)
Definition: req.c:1405
M0_INTERNAL int m0_dix_get(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *keys)
Definition: req.c:2434
static int dix_resolved_nr(struct m0_dix_req *req)
Definition: req.c:262
M0_INTERNAL uint32_t m0_dix_liter_spare_offset(struct m0_dix_layout_iter *iter)
Definition: layout.c:290
M0_INTERNAL void m0_dix_layout_iter_next(struct m0_dix_layout_iter *iter, uint64_t *tgt)
Definition: layout.c:249
Definition: req.h:185
uint32_t dcr_index_no
Definition: req_internal.h:72
static void dix_cas_rop_fini(struct m0_dix_cas_rop *cas_rop)
Definition: req.c:1284
m0_dix_req_state
Definition: req.h:94
static int dix_cas_rops_send(struct m0_dix_req *req)
Definition: req.c:1743
struct m0_fid pver
Definition: idx_dix.c:74
static int dix_cas_rops_fill(struct m0_dix_req *req)
Definition: req.c:2357
void m0_sm_state_set(struct m0_sm *mach, int state)
Definition: sm.c:478
m0_pool_nd_state
Definition: pool_machine.h:57
uint64_t dg_cas_reqs_nr
Definition: req_internal.h:169
M0_INTERNAL int m0_dix_ldescr_get(struct m0_dix_meta_req *req, const uint64_t *lid, uint32_t nr)
Definition: meta.c:506
uint64_t dgp_item
Definition: req_internal.h:152
struct m0_dix_idxop_ctx dr_idxop
Definition: req.h:242
Definition: tlist.h:251
M0_INTERNAL int m0_dix_meta_item_rc(const struct m0_dix_meta_req *req, uint64_t idx)
Definition: meta.c:314
struct m0_bufvec crp_keys
Definition: req_internal.h:101
M0_INTERNAL void m0_dix_req_lock(struct m0_dix_req *req)
Definition: req.c:184
M0_INTERNAL void m0_dix_req_init(struct m0_dix_req *req, struct m0_dix_cli *cli, struct m0_sm_group *grp)
Definition: req.c:228
M0_INTERNAL int m0_dix_req_wait(struct m0_dix_req *req, uint64_t states, m0_time_t to)
Definition: req.c:201
#define M0_BUF_INIT0
Definition: buf.h:71
static void dix_discovery(struct m0_dix_req *req)
Definition: req.c:1143
enum m0_conf_service_type sc_type
Definition: reqh_service.h:758
M0_INTERNAL int m0_dix_sm_conf_init(void)
Definition: req.c:2686
static bool dix_del_phase2_is_needed(const struct m0_dix_rec_op *rec_op)
Definition: req.c:1518
M0_INTERNAL int m0_cas_del(struct m0_cas_req *req, struct m0_cas_id *index, struct m0_bufvec *keys, struct m0_dtx *dtx, uint32_t flags)
Definition: client.c:1851
M0_INTERNAL uint32_t m0_dix_liter_unit_classify(struct m0_dix_layout_iter *iter, uint64_t unit)
Definition: layout.c:295
struct m0_sm_group * sm_grp
Definition: sm.h:321
M0_INTERNAL void m0_dix_meta_req_fini(struct m0_dix_meta_req *req)
Definition: meta.c:285
static void dix__rop(struct m0_dix_req *req, const struct m0_bufvec *keys, uint64_t *indices)
Definition: req.c:1356
uint32_t pd_sdev_idx
Definition: pool.h:437
static void dix_rop_failed_unit_tgt(struct m0_dix_req *req, struct m0_dix_rec_op *rec_op, uint64_t unit)
Definition: req.c:2055
#define M0_POST(cond)
M0_TL_DEFINE(cas_rop, M0_INTERNAL, struct m0_dix_cas_rop)
M0_INTERNAL void m0_sm_addb2_fini(struct m0_sm_conf *conf)
Definition: sm.c:870
struct m0_buf dgp_key
Definition: req_internal.h:144
struct m0_buf cge_val
Definition: client.h:207
static bool dix_item_parity_unit_is_last(const struct m0_dix_req *req, const struct m0_dix_item *item)
Definition: req.c:1454
struct m0_fop * ccr_fop
Definition: client.h:132
static int dix_type_layouts_nr(struct m0_dix_req *req, enum dix_layout_type type)
Definition: req.c:255
uint32_t dl_type
Definition: layout.h:100
uint32_t v_nr
Definition: vec.h:51
static void dix_cas_rop_rc_update(struct m0_dix_cas_rop *cas_rop, int rc)
Definition: req.c:1602
M0_INTERNAL void m0_dix_req_fini_lock(struct m0_dix_req *req)
Definition: req.c:2654
int32_t sm_rc
Definition: sm.h:336
struct m0_fid ci_fid
Definition: cas.h:113
M0_INTERNAL int m0_cas_index_create(struct m0_cas_req *req, const struct m0_cas_id *cids, uint64_t cids_nr, struct m0_dtx *dtx)
Definition: client.c:1324
struct m0_bufvec crp_vals
Definition: req_internal.h:102
struct m0_dix_cas_rop ** dg_target_rop
Definition: req_internal.h:166
struct m0_dix_idxop_req * dcd_idxop_reqs
Definition: req_internal.h:80
static struct m0_sm_trans_descr dix_req_trans[]
Definition: req.c:107
M0_INTERNAL void m0_buf_free(struct m0_buf *buf)
Definition: buf.c:55
static const struct m0_fid fids[]
Definition: diter.c:76
m0_bcount_t * v_count
Definition: vec.h:53
static void dix_rop_completed(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: req.c:1621
struct m0_pool_device_to_service * pc_dev2svc
Definition: pool.h:207
M0_INTERNAL int m0_dix_create(struct m0_dix_req *req, const struct m0_dix *indices, uint32_t indices_nr, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:990
union m0_dix_layout::@145 u
static int dix_rop_ctx_init(struct m0_dix_req *req, struct m0_dix_rop_ctx *rop, const struct m0_bufvec *keys, uint64_t *indices)
Definition: req.c:1302
struct m0_fid ld_pver
Definition: layout.h:78
#define FID_P(f)
Definition: fid.h:77
Definition: req.h:181
struct m0_layout_domain * dx_ldom
Definition: client.h:188
static bool dix_cas_rop_clink_cb(struct m0_clink *cl)
Definition: req.c:1696
uint64_t dg_completed_nr
Definition: req_internal.h:170
static int dix_spare_target_with_data(struct m0_dix_rec_op *rec_op, const struct m0_dix_pg_unit *failed_unit, uint32_t *spare_slot, struct m0_dix_pg_unit **spare_unit)
Definition: req.c:2007
static struct m0_pool pool
Definition: iter_ut.c:58
M0_INTERNAL void m0_dix_layout_iter_reset(struct m0_dix_layout_iter *iter)
Definition: layout.c:310
M0_INTERNAL int m0_cas_index_delete(struct m0_cas_req *req, const struct m0_cas_id *cids, uint64_t cids_nr, struct m0_dtx *dtx, uint32_t flags)
Definition: client.c:1369
M0_INTERNAL struct m0_layout * m0_pdl_to_layout(struct m0_pdclust_layout *pl)
Definition: pdclust.c:393
struct m0_reqh_service_ctx * pds_ctx
Definition: pool.h:74
M0_INTERNAL void m0_dix_ldesc_fini(struct m0_dix_ldesc *ld)
Definition: layout.c:197
bool dxi_del_phase2
Definition: req_internal.h:59
#define m0_forall(var, nr,...)
Definition: misc.h:112
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
struct m0_clink crp_clink
Definition: req_internal.h:97
static int dix_rop_del_phase2_rop(struct m0_dix_req *req, struct m0_dix_rop_ctx **out)
Definition: req.c:1524
struct m0_dix_rec_op * dg_rec_ops
Definition: req_internal.h:163
struct m0_pdclust_tgt_addr tgt
Definition: fd.c:110
M0_INTERNAL void m0_cas_index_delete_rep(const struct m0_cas_req *req, uint64_t idx, struct m0_cas_rec_reply *rep)
Definition: client.c:1397
static void dix_rec_op_fini(struct m0_dix_rec_op *rec_op)
Definition: req.c:1260
static void dix_req_failure(struct m0_dix_req *req, int32_t rc)
Definition: req.c:249
M0_INTERNAL void m0_cas_del_rep(struct m0_cas_req *req, uint64_t idx, struct m0_cas_rec_reply *rep)
Definition: client.c:1882
M0_INTERNAL void m0_dtx0_executed(struct m0_dtx *dtx, uint32_t pa_idx)
Definition: dtx.c:526
uint64_t dit_unit
Definition: layout.h:141
uint64_t dcd_cas_reqs_nr
Definition: req_internal.h:82
static void dix_discovery_ast(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: req.c:1128
M0_INTERNAL int m0_dtx0_fid_assign(struct m0_dtx *dtx, uint32_t pa_idx, const struct m0_fid *pa_sfid)
Definition: dtx.c:503
static int dix_indices_copy(struct m0_dix **dst_indices, const struct m0_dix *src_indices, uint32_t indices_nr)
Definition: req.c:431
struct m0_sm_conf dix_req_sm_conf
Definition: req.c:135
void * dr_sync_datum
Definition: req.h:260
static void dix_idxop(struct m0_dix_req *req)
Definition: req.c:963
Definition: req.h:183
Definition: fid.h:38
struct m0_pool_version * dg_pver
Definition: req_internal.h:172
uint64_t dgp_units_nr
Definition: req_internal.h:154
M0_INTERNAL void m0_dtx0_fop_assign(struct m0_dtx *dtx, uint32_t pa_idx, const struct m0_fop *pa_fop)
Definition: dtx.c:511
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
struct m0_dix_crop_attrs * crp_attrs
Definition: req_internal.h:104
uint32_t psu_device_index
Definition: pool.h:413
#define M0_IS0(obj)
Definition: misc.h:70
M0_INTERNAL int m0_cas_index_lookup(struct m0_cas_req *req, const struct m0_cas_id *cids, uint64_t cids_nr)
Definition: client.c:1406
static int dix_req_indices_copy(struct m0_dix_req *req, const struct m0_dix *indices, uint32_t indices_nr)
Definition: req.c:460
M0_INTERNAL void m0_dix_sm_conf_fini(void)
Definition: req.c:2694
static int dix_spare_slot_find(struct m0_poolmach_state *pm_state, uint64_t failed_tgt, uint32_t *spare_slot)
Definition: req.c:1915
static int dix__spare_target(struct m0_dix_rec_op *rec_op, const struct m0_dix_pg_unit *failed_unit, uint32_t *spare_slot, struct m0_dix_pg_unit **spare_unit, bool with_data)
Definition: req.c:1951
#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_dtx * dr_dtx
Definition: req.h:240
static uint32_t dix_rec_op_spare_offset(struct m0_dix_rec_op *rec_op)
Definition: req.c:1946
static void dix_rop(struct m0_dix_req *req)
Definition: req.c:1394
static void dix_rop_tgt_iter_begin(const struct m0_dix_req *req, struct m0_dix_rec_op *rec_op)
Definition: req.c:1867
static void dix_req_init(struct m0_dix_req *req, struct m0_dix_cli *cli, struct m0_sm_group *grp, bool meta)
Definition: req.c:209
M0_INTERNAL int m0_dix_del(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *keys, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:2465
static void dix_ldescr_resolve(struct m0_dix_req *req)
Definition: req.c:1032
static void dix_discovery_completed(struct m0_dix_req *req)
Definition: req.c:1100
M0_INTERNAL int m0_dix_meta_generic_rc(const struct m0_dix_meta_req *req)
Definition: meta.c:309
static int dix_rec_op_init(struct m0_dix_rec_op *rec_op, struct m0_dix_req *req, struct m0_dix_cli *cli, struct m0_pool_version *pver, struct m0_dix *dix, struct m0_buf *key, uint64_t user_item)
Definition: req.c:1233
struct m0_sm_ast dg_ast
Definition: req_internal.h:173
M0_INTERNAL int m0_cas_put(struct m0_cas_req *req, struct m0_cas_id *index, const struct m0_bufvec *keys, const struct m0_bufvec *values, struct m0_dtx *dtx, uint32_t flags)
Definition: client.c:1652
static struct m0_sm_state_descr dix_req_states[]
Definition: req.c:50
uint32_t pa_P
Definition: pdclust.h:115
static void dix_to_cas_map(const struct m0_dix_req *dreq, const struct m0_cas_req *creq)
Definition: req.c:175
uint32_t id_nr
Definition: io_fops.h:278
M0_TL_DESCR_DEFINE(cas_rop, "cas record operations", M0_INTERNAL, struct m0_dix_cas_rop, crp_linkage, crp_magix, M0_DIX_ROP_MAGIC, M0_DIX_ROP_HEAD_MAGIC)
M0_INTERNAL uint32_t m0_dix_liter_N(struct m0_dix_layout_iter *iter)
Definition: layout.c:270
uint32_t crp_pa_idx
Definition: req_internal.h:112
static int dix_cas_rops_alloc(struct m0_dix_req *req)
Definition: req.c:2215
uint32_t crp_flags
Definition: req_internal.h:96
static int dix_cas_rop_alloc(struct m0_dix_req *req, uint32_t sdev, struct m0_dix_cas_rop **cas_rop)
Definition: req.c:1266
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
uint32_t dgp_next_tgt
Definition: req_internal.h:150
static struct m0_fop * fop
Definition: item.c:57
M0_INTERNAL void m0_rwlock_read_lock(struct m0_rwlock *lock)
Definition: rwlock.c:52
M0_INTERNAL void m0_dix_req_unlock(struct m0_dix_req *req)
Definition: req.c:190
M0_INTERNAL int m0_dix_meta_req_nr(const struct m0_dix_meta_req *req)
Definition: meta.c:321
M0_INTERNAL void m0_sm_group_lock(struct m0_sm_group *grp)
Definition: sm.c:83
M0_INTERNAL void m0_dix_get_rep_mlock(struct m0_dix_req *req, uint64_t idx)
Definition: req.c:2586
static void dix_idxop_completed(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: req.c:528
struct m0_clink dr_clink
Definition: req.h:201
struct m0_pdclust_layout * li_pl
Definition: layout.h:115
#define M0_ASSERT_INFO(cond, fmt,...)
static void dix_idxop_item_rc_update(struct m0_dix_item *ditem, struct m0_dix_req *req, const struct m0_dix_cas_req *creq)
Definition: req.c:489
M0_INTERNAL void m0_cas_rep_mlock(const struct m0_cas_req *req, uint64_t idx)
Definition: client.c:1825
Definition: pool.h:80
M0_INTERNAL int m0_dix_layout_del(struct m0_dix_meta_req *req, const struct m0_fid *fid, uint32_t nr)
Definition: meta.c:603
M0_INTERNAL struct m0_pool_version * m0_dix_pver(const struct m0_dix_cli *cli, const struct m0_dix *dix)
Definition: client.c:309
uint32_t crp_keys_nr
Definition: req_internal.h:99
struct m0_tl dg_cas_reqs
Definition: req_internal.h:168
static void dix_rop_ctx_fini(struct m0_dix_rop_ctx *rop)
Definition: req.c:1343
struct m0_dix * dr_indices
Definition: req.h:214
struct m0_cas_req ds_creq
Definition: req_internal.h:65
struct m0_rwlock pm_lock
Definition: pool_machine.h:178
M0_INTERNAL void m0_rwlock_read_unlock(struct m0_rwlock *lock)
Definition: rwlock.c:57
static struct m0_pool_version * dix_pver_find(const struct m0_dix_req *req, const struct m0_fid *pver_fid)
Definition: req.c:474
struct m0_sm_ast dr_ast
Definition: req.h:246
enum dix_req_type dr_type
Definition: req.h:248
#define out(...)
Definition: gen.c:41
static void dix_item_fini(const struct m0_dix_req *req, struct m0_dix_item *item)
Definition: req.c:2615
int type
Definition: dir.c:1031
static void dix_to_mdix_map(const struct m0_dix_req *req, const struct m0_dix_meta_req *mreq)
Definition: req.c:277
M0_INTERNAL void m0_sm_conf_fini(struct m0_sm_conf *conf)
Definition: sm.c:376
M0_INTERNAL void m0_dix_next_rep_mlock(struct m0_dix_req *req, uint32_t key_idx, uint32_t val_idx)
Definition: req.c:2596
uint32_t crp_cur_key
Definition: req_internal.h:100
struct m0_rpc_link sc_rlink
Definition: reqh_service.h:760
struct m0_dix_next_results * nrs_res
Definition: req.h:166
static void dix_rop_units_set(struct m0_dix_req *req)
Definition: req.c:2148
struct m0_chan dmr_chan
Definition: meta.h:97
static int dix_unknown_layouts_nr(struct m0_dix_req *req)
Definition: req.c:272
M0_INTERNAL void m0_dix_next_rep(const struct m0_dix_req *req, uint64_t key_idx, uint64_t val_idx, struct m0_dix_next_reply *rep)
Definition: req.c:2526
M0_INTERNAL uint64_t m0_sm_id_get(const struct m0_sm *sm)
Definition: sm.c:1021
M0_INTERNAL bool m0_dix_req_is_locked(const struct m0_dix_req *req)
Definition: req.c:196
#define m0_tl_for(name, head, obj)
Definition: tlist.h:695
void m0_free(void *data)
Definition: memory.c:146
static bool dix_idxop_meta_update_clink_cb(struct m0_clink *cl)
Definition: req.c:820
M0_INTERNAL uint32_t m0_dix_next_rep_nr(const struct m0_dix_req *req, uint64_t key_idx)
Definition: req.c:2545
struct m0_rpc_item f_item
Definition: fop.h:84
static int dix_spare_target(struct m0_dix_rec_op *rec_op, const struct m0_dix_pg_unit *failed_unit, uint32_t *spare_slot, struct m0_dix_pg_unit **spare_unit)
Definition: req.c:1998
Definition: cas.h:107
#define M0_BUF_INIT(size, data)
Definition: buf.h:64
uint32_t sm_state
Definition: sm.h:307
struct m0_pdclust_attr pv_attr
Definition: pool.h:122
struct m0_pdclust_src_addr src
Definition: fd.c:108
M0_INTERNAL void m0_bufvec_free2(struct m0_bufvec *bufvec)
Definition: vec.c:401
static void dix_pg_unit_pd_assign(struct m0_dix_pg_unit *pgu, struct m0_pooldev *pd)
Definition: req.c:2039
M0_INTERNAL void m0_dix_fid_convert_dix2cctg(const struct m0_fid *dix_fid, struct m0_fid *cctg_fid, uint32_t device_id)
Definition: fid_convert.c:54
M0_INTERNAL uint32_t m0_dix_liter_P(struct m0_dix_layout_iter *iter)
Definition: layout.c:275
int32_t rc
Definition: trigger_fop.h:47
struct m0_pool_spare_usage * pst_spare_usage_array
Definition: pool_machine.h:137
static bool dix_pg_unit_skip(struct m0_dix_req *req, struct m0_dix_pg_unit *unit)
Definition: req.c:2206
#define ARRAY_SIZE(a)
Definition: misc.h:45
uint32_t pd_index
Definition: pool.h:432
uint32_t crp_sdev_idx
Definition: req_internal.h:98
M0_INTERNAL void m0_cas_index_lookup_rep(const struct m0_cas_req *req, uint64_t idx, struct m0_cas_rec_reply *rep)
Definition: client.c:1429
struct m0_buf cnp_key
Definition: client.h:219
M0_INTERNAL int m0_dix_cctgs_lookup(struct m0_dix_req *req, const struct m0_dix *indices, uint32_t indices_nr)
Definition: req.c:1214
M0_INTERNAL bool m0_sm_group_is_locked(const struct m0_sm_group *grp)
Definition: sm.c:107
static struct m0_sm_state_descr states[C_NR]
Definition: sm.c:512
struct m0_dix_req * crp_parent
Definition: req_internal.h:93
M0_INTERNAL int m0_dix_put(struct m0_dix_req *req, const struct m0_dix *index, const struct m0_bufvec *keys, const struct m0_bufvec *vals, struct m0_dtx *dtx, uint32_t flags)
Definition: req.c:2401
M0_INTERNAL struct m0_pooldev * m0_dix_tgt2sdev(struct m0_dix_linst *linst, uint64_t tgt)
Definition: layout.c:76
Definition: fop.h:80
#define FID_F
Definition: fid.h:75
M0_INTERNAL void m0_dix_fini(struct m0_dix *dix)
Definition: req.c:2680
Definition: vec.h:145
Definition: req.h:110
M0_INTERNAL int m0_bufvec_empty_alloc(struct m0_bufvec *bufvec, uint32_t num_segs)
Definition: vec.c:213
static int dix_idxop_pver_analyse(struct m0_dix_idxop_req *idxop_req, struct m0_dix_req *dreq, uint64_t *creqs_nr)
Definition: req.c:599
enum m0_pool_nd_state dpu_pd_state
Definition: req_internal.h:130
Definition: idx_mock.c:47
M0_INTERNAL int m0_dix_generic_rc(const struct m0_dix_req *req)
Definition: req.c:2560
#define m0_tl_forall(name, var, head,...)
Definition: tlist.h:735
static int dix_idxop_req_send(struct m0_dix_idxop_req *idxop_req, struct m0_dix_req *dreq, uint64_t *reqs_acc)
Definition: req.c:670
#define M0_IMPOSSIBLE(fmt,...)
M0_INTERNAL void m0_sm_fini(struct m0_sm *mach)
Definition: sm.c:331
struct m0_tl po_failed_devices
Definition: pool.h:93