Motr  M0
iter.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2016-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_DIXCM
24 #include <unistd.h>
25 #include "lib/trace.h"
26 
27 #include "lib/memory.h"
28 #include "sm/sm.h"
29 #include "fop/fom.h"
30 #include "dix/cm/cm.h" /* m0_dix_cm_type */
31 
32 #include "pool/pool.h"
33 #include "pool/pool_machine.h"
34 #include "reqh/reqh.h"
35 #include "lib/finject.h"
36 
37 #include "dix/fid_convert.h"
38 #include "dix/cm/iter.h"
39 
67  DIX_ITER_EOF, /* 20 */
68  DIX_ITER_FAILURE, /* 21 */
69 };
70 
72  [DIX_ITER_INIT] = {
74  .sd_name = "init",
75  .sd_allowed = M0_BITS(DIX_ITER_STARTED)
76  },
77  [DIX_ITER_STARTED] = {
78  .sd_name = "started",
79  .sd_allowed = M0_BITS(DIX_ITER_DEL_LOCK, DIX_ITER_EOF)
80  },
81  [DIX_ITER_DEL_LOCK] = {
82  .sd_name = "self-lock",
83  .sd_allowed = M0_BITS(DIX_ITER_CTIDX_START)
84  },
86  .sd_name = "ctidx-first-key",
88  },
90  .sd_name = "ctidx-reposition",
92  },
94  .sd_name = "ctidx-next",
96  },
97  [DIX_ITER_NEXT_CCTG] = {
98  .sd_name = "next-cctg",
99  .sd_allowed = M0_BITS(DIX_ITER_META_LOCK,
100  DIX_ITER_EOF,
102  },
103  [DIX_ITER_META_LOCK] = {
104  .sd_name = "meta-lock",
106  },
108  .sd_name = "cctg-meta-lookup",
109  .sd_allowed = M0_BITS(DIX_ITER_CCTG_START,
113  },
114  [DIX_ITER_CCTG_START] = {
115  .sd_name = "cctg-first-record",
117  },
119  .sd_name = "cctg-cur-next",
121  },
122  [DIX_ITER_NEXT_KEY] = {
123  .sd_name = "next-key",
124  .sd_allowed = M0_BITS(DIX_ITER_IDLE_START,
128  },
129  [DIX_ITER_IDLE_START] = {
130  .sd_name = "idle-start",
131  .sd_allowed = M0_BITS(DIX_ITER_IDLE_FIN,
133  },
135  .sd_name = "del_tx_opened",
137  },
139  .sd_name = "del_tx_wait",
141  },
143  .sd_name = "del_tx_done",
145  },
146  [DIX_ITER_IDLE_FIN] = {
147  .sd_name = "idle-fin",
149  },
150  [DIX_ITER_CCTG_CHECK] = {
151  .sd_name = "del-check",
152  .sd_allowed = M0_BITS(DIX_ITER_CCTG_CONT,
154  },
155  [DIX_ITER_CCTG_CONT] = {
156  .sd_name = "cctg-continue",
158  },
159  [DIX_ITER_EOF] = {
160  .sd_name = "end-of-iterator",
161  .sd_allowed = M0_BITS(DIX_ITER_FINAL)
162  },
163  [DIX_ITER_FINAL] = {
164  .sd_name = "final",
165  .sd_flags = M0_SDF_TERMINAL,
166  },
167  [DIX_ITER_FAILURE] = {
168  .sd_name = "failure",
169  .sd_allowed = M0_BITS(DIX_ITER_FINAL),
170  .sd_flags = M0_SDF_FAILURE
171  }
172 };
173 
176  { "start", DIX_ITER_INIT, DIX_ITER_STARTED },
177  { "get-first-key", DIX_ITER_STARTED, DIX_ITER_CTIDX_NEXT },
179  { "no-more-indices", DIX_ITER_IDLE_START, DIX_ITER_EOF },
180  { "next-key-fetched", DIX_ITER_NEXT_KEY, DIX_ITER_IDLE_START },
181  { "index-eof", DIX_ITER_NEXT_KEY, DIX_ITER_NEXT_CCTG },
182  { "failure", DIX_ITER_NEXT_KEY, DIX_ITER_FAILURE },
183  { "get-first-key", DIX_ITER_NEXT_CCTG, DIX_ITER_CCTG_LOOKUP },
184  { "no-more-indices", DIX_ITER_NEXT_CCTG, DIX_ITER_EOF },
185  { "failure", DIX_ITER_NEXT_CCTG, DIX_ITER_FAILURE },
186  { "get-first-key", DIX_ITER_CCTG_LOOKUP, DIX_ITER_NEXT_KEY },
187  { "cctg-not-found", DIX_ITER_CCTG_LOOKUP, DIX_ITER_FAILURE },
188  { "finalise", DIX_ITER_EOF, DIX_ITER_FINAL },
189  { "finalise", DIX_ITER_FAILURE, DIX_ITER_FINAL },
190 };
191 
192 static const struct m0_sm_conf dix_cm_iter_sm_conf = {
193  .scf_name = "dix_cm_iter",
194  .scf_nr_states = ARRAY_SIZE(dix_cm_iter_phases),
195  .scf_state = dix_cm_iter_phases,
196  .scf_trans_nr = ARRAY_SIZE(dix_cm_iter_trans),
197  .scf_trans = dix_cm_iter_trans
198 };
199 
200 static int dix_cm_iter_buf_copy(struct m0_buf *dst,
201  struct m0_buf *src,
202  m0_bcount_t cutoff)
203 {
204  M0_PRE(dst->b_nob == 0 && dst->b_addr == NULL);
205 
206  return src->b_nob >= cutoff ?
208  m0_buf_copy(dst, src);
209 }
210 
211 static uint64_t dix_cm_iter_fom_locality(const struct m0_fom *fom)
212 {
213  return fom->fo_type->ft_id;
214 }
215 
216 static bool dix_cm_iter_meta_clink_cb(struct m0_clink *cl)
217 {
218  struct m0_dix_cm_iter *iter = M0_AMB(iter, cl, di_meta_clink);
219 
220  iter->di_meta_modified = true;
221  return false;
222 }
223 
224 static void dix_cm_iter_init(struct m0_dix_cm_iter *iter)
225 {
226  struct m0_fom *fom = &iter->di_fom;
227 
228  iter->di_tgts = NULL;
229  iter->di_tgts_cur = 0;
230  iter->di_tgts_nr = 0;
231  iter->di_stop = false;
232 
233  M0_SET0(&iter->di_key);
234  M0_SET0(&iter->di_val);
235 
236  iter->di_processed_recs_nr = 0;
237  iter->di_cctg_processed_recs_nr = 0;
238 
242  &iter->di_lock_addb2);
244  &iter->di_meta_lock_addb2);
246  &iter->di_del_lock_addb2);
247 
248  /* Subscribe to meta catalogue modifications. */
251  &iter->di_meta_clink);
252 }
253 
254 static void dix_cm_iter_dtx_fini(struct m0_dix_cm_iter *iter)
255 {
256  struct m0_fom *fom = &iter->di_fom;
257 
258  m0_dtx_fini(&fom->fo_tx);
260 }
261 
262 static void dix_cm_iter_tgts_fini(struct m0_dix_cm_iter *iter)
263 {
264  m0_free(iter->di_tgts);
265  iter->di_tgts = NULL;
266  iter->di_tgts_cur = 0;
267  iter->di_tgts_nr = 0;
268 }
269 
270 static void dix_cm_iter_fini(struct m0_dix_cm_iter *iter)
271 {
272  M0_ENTRY();
273 
274  if (iter->di_cctg != NULL)
279  m0_buf_free(&iter->di_prev_key);
280  m0_buf_free(&iter->di_key);
281  m0_buf_free(&iter->di_val);
282  dix_cm_iter_tgts_fini(iter);
287  m0_ctg_op_fini(&iter->di_ctidx_op);
290  M0_LEAVE();
291 }
292 
293 static int dix_cm_iter_failure(struct m0_dix_cm_iter *iter, int rc)
294 {
295  M0_PRE(rc < 0);
298  return M0_FSO_WAIT;
299 }
300 
301 static int dix_cm_iter_eof(struct m0_dix_cm_iter *iter)
302 {
305  return M0_FSO_WAIT;
306 }
307 
308 static int dix_cm_iter_idle(struct m0_dix_cm_iter *iter)
309 {
312  return M0_FSO_WAIT;
313 }
314 
315 static int dix_cm_iter_dtx_failure(struct m0_dix_cm_iter *iter)
316 {
317  struct m0_fom *fom = &iter->di_fom;
318  struct m0_be_tx *tx = m0_fom_tx(fom);
319 
320  dix_cm_iter_dtx_fini(iter);
321  return dix_cm_iter_failure(iter, tx->t_sm.sm_rc);
322 }
323 
324 static struct m0_poolmach *dix_cm_pm_get(struct m0_dix_cm *dix_cm,
325  struct m0_dix_layout *layout)
326 {
327  struct m0_reqh *reqh;
328  struct m0_pool_version *pver;
329 
330  M0_PRE(dix_cm != NULL);
331  M0_PRE(layout != NULL);
332 
333  reqh = dix_cm->dcm_base.cm_service.rs_reqh;
335  &layout->u.dl_desc.ld_pver);
336  return &pver->pv_mach;
337 }
338 
340  const struct m0_fid *index,
341  struct m0_dix_layout *layout,
342  struct m0_dix_cm *dix_cm,
343  struct m0_buf *key)
344 {
345  struct m0_reqh *reqh;
346  struct m0_layout_domain *ldom;
347  struct m0_pool_version *pver;
348 
349  M0_PRE(index != NULL);
350  M0_PRE(layout != NULL);
351  M0_PRE(dix_cm != NULL);
352  M0_PRE(key != NULL);
353 
354  reqh = dix_cm->dcm_base.cm_service.rs_reqh;
355  ldom = &reqh->rh_ldom;
357  &layout->u.dl_desc.ld_pver);
358  return m0_dix_layout_iter_init(iter, index, ldom, pver,
359  &layout->u.dl_desc, key);
360 }
361 
362 
363 static int dix_cm_tgt_to_unit(uint64_t tgt,
364  uint64_t *group_tgts,
365  uint64_t group_tgts_nr,
366  uint64_t *unit)
367 {
368  uint64_t i;
369  int rc = 0;
370 
371  M0_PRE(group_tgts != NULL);
372  M0_PRE(unit != NULL);
373 
374  *unit = 0;
375 
376  for (i = 0; i < group_tgts_nr; i++) {
377  if (group_tgts[i] == tgt) {
378  *unit = i;
379  break;
380  }
381  }
382 
383  if (i == group_tgts_nr)
384  rc = M0_ERR(-ENOENT);
385 
386  return M0_RC(rc);
387 }
388 
389 static
391  struct m0_poolmach *pm,
392  uint64_t *group_tgts,
393  uint64_t group_tgts_nr,
394  uint64_t spare_id)
395 {
396  uint64_t spare_id_loc;
397  uint64_t unit;
398  uint64_t device_index;
399  struct m0_pool_spare_usage *spare_usage_array;
400  bool has_data = false;
401  int rc;
402 
403  if (spare_id == 0)
404  return false;
405 
406  spare_usage_array = pm->pm_state->pst_spare_usage_array;
407  spare_id_loc = spare_id;
408  device_index = spare_usage_array[spare_id_loc].psu_device_index;
409 
410  /*
411  * Go backward through spare usage array starting from the previous unit
412  * relative to passed spare unit to check whether passed spare unit
413  * contains data as a result of previous data reconstructions
414  * (a.g. resolve "failures chain").
415  */
416  do {
417  M0_CNT_DEC(spare_id_loc);
418 
419  /* Skip device that is not in the current "failure chain". */
420  unit = spare_id_loc + m0_dix_liter_N(iter) +
421  m0_dix_liter_K(iter);
422  if (group_tgts[unit] != device_index)
423  continue;
424 
425  /*
426  * Convert previously failed device to unit number inside of
427  * parity group.
428  */
429  device_index = spare_usage_array[spare_id_loc].
431  M0_ASSERT(device_index != POOL_PM_SPARE_SLOT_UNUSED);
432 
433  rc = dix_cm_tgt_to_unit(device_index,
434  group_tgts,
435  group_tgts_nr,
436  &unit);
437  /*
438  * It may occur that previously failed device is outside of
439  * current parity group, break current failure chain in this
440  * case.
441  */
442  M0_ASSERT(rc == 0 || rc == -ENOENT);
443  if (rc == -ENOENT)
444  break;
445  /*
446  * Go further if previously failed device serves spare unit
447  * until:
448  * - failed device is mapped to data or parity unit;
449  * - all previuos spare units of parity group are checked.
450  */
451  if (m0_dix_liter_unit_classify(iter, unit) != M0_PUT_SPARE) {
452  /*
453  * Device that serves data unit or parity unit is failed
454  * initially, set has_data to true if it was repaired,
455  * leave as false otherwise and break the loop.
456  */
457  if (spare_usage_array[spare_id_loc].psu_device_state !=
459  has_data = true;
460  break;
461  }
462  } while (spare_id_loc > 0);
463 
464  return has_data;
465 }
466 
468  struct m0_poolmach *pm,
469  uint64_t *group_tgts,
470  uint64_t group_tgts_nr,
471  uint64_t spare_id,
472  uint64_t **tgts,
473  uint64_t *tgts_nr)
474 {
475  uint32_t N;
476  uint32_t K;
477  uint64_t unit;
478  uint64_t tgt_tmp;
479  uint64_t device_index;
480  uint64_t spare_id_loc;
481  struct m0_pool_spare_usage *spare_usage_array;
482  bool is_set = false;
483  bool has_data = false;
484  bool is_first_cycle = true;
485  int rc = 0;
486 
487  *tgts = NULL;
488  *tgts_nr = 0;
489 
490  spare_usage_array = pm->pm_state->pst_spare_usage_array;
491 
492  spare_id_loc = spare_id;
493  N = m0_dix_liter_N(iter);
494  K = m0_dix_liter_K(iter);
495 
496  do {
497  if (!is_first_cycle) {
498  M0_CNT_DEC(spare_id_loc);
499  unit = spare_id_loc + N + K;
500  if (group_tgts[unit] != device_index) {
501  continue;
502  }
503  } else
504  is_first_cycle = false;
505  /*
506  * Convert previously failed device to unit number inside of
507  * parity group.
508  */
509  device_index = spare_usage_array[spare_id_loc].
511  /*
512  * Skip unused slots as they may occur as a result of
513  * successive repair/rebalance processes.
514  */
515  if (device_index == POOL_PM_SPARE_SLOT_UNUSED)
516  continue;
517  rc = dix_cm_tgt_to_unit(device_index,
518  group_tgts,
519  group_tgts_nr,
520  &unit);
521  /*
522  * It may occur that previously failed device is outside of
523  * current parity group, break current failure chain in this
524  * case.
525  */
526  M0_ASSERT(rc == 0 || rc == -ENOENT);
527  if (rc == -ENOENT)
528  break;
529  /*
530  * We are looking for the last rebalancing device in failure
531  * chain, full failure chain should be checked.
532  */
533  if (spare_usage_array[spare_id_loc].psu_device_state ==
535  /*
536  * Rebalancing device found during checking of failure
537  * chain, set it as target candidate.
538  */
539  tgt_tmp = device_index;
540  is_set = true;
541  }
542  if (m0_dix_liter_unit_classify(iter, unit) != M0_PUT_SPARE) {
543  /*
544  * Non-spare slot achieved during checking of failure
545  * chain, it means that served locally spare contains
546  * real data.
547  */
548  has_data = true;
549  break;
550  }
551  } while (spare_id_loc > 0);
552 
553  if (is_set && has_data) {
554  M0_ALLOC_ARR(*tgts, 1);
555  if (*tgts == NULL)
556  rc = M0_ERR(-ENOMEM);
557  else {
558  *tgts[0] = tgt_tmp;
559  *tgts_nr = 1;
560  }
561  }
562 
563  return M0_RC(rc);
564 }
565 
567  struct m0_poolmach *pm,
568  uint64_t **tgts,
569  uint64_t *tgts_nr)
570 {
571  uint32_t i;
572  uint64_t unit;
573  uint64_t units_nr;
574  uint64_t spare_nr;
575  uint64_t spare_id;
576  uint64_t tgt_tmp;
577  uint64_t *group_tgts;
578  uint64_t group_tgts_nr;
579  uint64_t device_index;
580  uint32_t device_state;
581  uint64_t *tgts_loc;
582  uint64_t tgts_nr_loc;
583  struct m0_pool_spare_usage *spare_usage_array;
584  enum m0_pool_nd_state state;
585  int rc = 0;
586 
587  M0_PRE(iter != NULL);
588  M0_PRE(pm != NULL);
589  M0_PRE(tgts != NULL);
590  M0_PRE(tgts_nr != NULL);
591 
592  *tgts = NULL;
593  *tgts_nr = 0;
594 
595  if (M0_FI_ENABLED("single_target")) {
596  *tgts_nr = 1;
597  M0_ALLOC_ARR(*tgts, *tgts_nr);
598  (*tgts)[0] = 1;
599  return 0;
600  }
601 
603 
604  /*
605  * Firstly get all target devices of parity group that the key belongs
606  * to, it is needed to skip failed target devices that are not
607  * considered in scope of current parity group.
608  */
609  group_tgts_nr = m0_dix_liter_W(iter);
610  M0_ALLOC_ARR(group_tgts, group_tgts_nr);
611  if (group_tgts == NULL)
612  return M0_ERR(-ENOMEM);
613 
614  unit = 0;
615  units_nr = group_tgts_nr;
616 
617  while (unit < units_nr) {
618  m0_dix_layout_iter_next(iter, &tgt_tmp);
619  group_tgts[unit] = tgt_tmp;
620  M0_CNT_INC(unit);
621  }
622 
623  /*
624  * Allocate memory for resulting target devices, precise number of
625  * targets is not determined at this stage, so allocate array of length
626  * that equals to the count of all spare units in parity group).
627  * It guarantees that such number of array elements is enough to store
628  * resulting targets. Actual number of resulting targets will be set at
629  * the end of the algo, set it to 0 initially.
630  */
631  tgts_nr_loc = 0;
633  if (tgts_loc == NULL) {
634  rc = M0_ERR(-ENOMEM);
635  goto out;
636  }
637 
639 
640  spare_usage_array = pm->pm_state->pst_spare_usage_array;
641  spare_nr = pm->pm_state->pst_nr_spares;
642 
643  /*
644  * Go through the spare usage array to determine target devices where
645  * current key-value record should be reconstructed.
646  */
647  for (i = 0; i < spare_nr; i++) {
648  spare_id = i;
649  device_index = spare_usage_array[spare_id].psu_device_index;
650  device_state = spare_usage_array[spare_id].psu_device_state;
651 
652  /* Unused slot is achieved, does not make sense to continue. */
653  if (device_index == POOL_PM_SPARE_SLOT_UNUSED)
654  break;
655  /*
656  * Skip device if it is not under repairing or it is not in
657  * the devices set of current parity group.
658  */
659  if (device_state != M0_PNDS_SNS_REPAIRING ||
660  !m0_exists(j, group_tgts_nr, group_tgts[j] == device_index))
661  continue;
662 
663  /* Get target device where current spare unit is stored. */
664  tgt_tmp = group_tgts[spare_id + m0_dix_liter_N(iter) +
665  m0_dix_liter_K(iter)];
666  /* Skip spare unit if it is not online. */
667  state = pm->pm_state->pst_devices_array[tgt_tmp].pd_state;
668  if (state != M0_PNDS_ONLINE)
669  continue;
670 
671  rc = dix_cm_tgt_to_unit(device_index,
672  group_tgts,
673  group_tgts_nr,
674  &unit);
675  /* Must be true, check the logic otherwise. */
676  M0_ASSERT(rc == 0);
677  /* Skip empty spare unit. */
678  if (m0_dix_liter_unit_classify(iter, unit) == M0_PUT_SPARE &&
679  !dix_cm_repair_spare_has_data(iter, pm, group_tgts,
680  group_tgts_nr, spare_id))
681  continue;
682 
683  M0_ASSERT(!m0_exists(j, tgts_nr_loc, tgts_loc[j] == tgt_tmp));
684  tgts_loc[tgts_nr_loc] = tgt_tmp;
685  M0_CNT_INC(tgts_nr_loc);
686  }
687 
689 out:
690  m0_free(group_tgts);
691  if (rc == 0 && tgts_nr_loc > 0) {
692  *tgts = tgts_loc;
693  *tgts_nr = tgts_nr_loc;
694  } else
695  m0_free(tgts_loc);
696 
697  return M0_RC(rc);
698 }
699 
700 static void parity_group_print(struct m0_dix_layout_iter *iter,
701  struct m0_poolmach *pm,
702  uint64_t local_device,
703  struct m0_buf *key)
704 {
705  uint64_t unit;
706  uint64_t units_nr;
707  uint64_t tgt;
708  struct m0_pooldev *global_dev;
709  enum m0_pool_nd_state state;
710 
712 
713  unit = 0;
714  units_nr = m0_dix_liter_W(iter);
715 
716  M0_LOG(M0_DEBUG, "Parity group info for key %"PRIu64
717  " (pool dev_id/global dev_id):",
718  be64toh(*(uint64_t *)key->b_addr));
719  M0_LOG(M0_DEBUG, "=============================================");
720  while (unit < units_nr) {
722  M0_ASSERT(tgt < pm->pm_state->pst_nr_devices);
723  state = pm->pm_state->pst_devices_array[tgt].pd_state;
724  global_dev = m0_dix_tgt2sdev(&iter->dit_linst, tgt);
726  "%" PRIu64 "%s: dev_id: %" PRIu64 "/%u, %s, %s%s",
727  unit,
728  units_nr > 10 ? (unit < 10 ? " " : "") : "",
729  tgt,
730  global_dev->pd_sdev_idx,
731  unit < m0_dix_liter_N(iter) ?
732  " data" :
733  unit < m0_dix_liter_N(iter) + m0_dix_liter_K(iter) ?
734  "parity" :
735  " spare",
737  local_device == global_dev->pd_sdev_idx ?
738  ", (local)" : "");
739  M0_CNT_INC(unit);
740  }
741  M0_LOG(M0_DEBUG, "=============================================");
742 }
743 
744 static void spare_usage_print(struct m0_dix_layout_iter *iter,
745  struct m0_poolmach *pm)
746 {
747  uint32_t i;
748  uint64_t tgt;
749  struct m0_pooldev *global_dev;
750  uint32_t max_device_failures;
751  uint32_t spare_nr;
752  struct m0_pool_spare_usage *spare_usage_array;
753  enum m0_pool_nd_state state;
754 
756  m0_dix_liter_K(iter));
757 
758  spare_usage_array = pm->pm_state->pst_spare_usage_array;
759  max_device_failures = pm->pm_state->pst_max_device_failures;
760  spare_nr = pm->pm_state->pst_nr_spares;
761 
763  "Spare usage array info (pool dev_id/global dev_id):");
764  M0_LOG(M0_DEBUG, "=============================================");
765  for (i = 0; i < spare_nr; i++) {
766  tgt = spare_usage_array[i].psu_device_index;
768  state = spare_usage_array[i].psu_device_state;
769  global_dev = m0_dix_tgt2sdev(&iter->dit_linst, tgt);
771  "%u: dev_id: %" PRIu64 "/%u, %s, served by:",
772  i,
773  tgt,
774  global_dev->pd_sdev_idx,
775  m0_pool_dev_state_to_str(state));
776  } else
777  M0_LOG(M0_DEBUG, "%u: slot unused, served by:",
778  i);
779 
781  M0_ASSERT(tgt < pm->pm_state->pst_nr_devices);
782  state = pm->pm_state->pst_devices_array[tgt].pd_state;
783  global_dev = m0_dix_tgt2sdev(&iter->dit_linst, tgt);
785  "%s dev_id: %" PRIu64 "/%u, %s",
786  max_device_failures > 10 ? " " : " ",
787  tgt,
788  global_dev->pd_sdev_idx,
789  m0_pool_dev_state_to_str(state));
790  }
791  M0_LOG(M0_DEBUG, "=============================================");
792 }
793 
794 static void tgts_print(struct m0_dix_layout_iter *iter,
795  uint64_t *tgts,
796  uint64_t tgts_nr,
797  struct m0_buf *key)
798 {
799  struct m0_pooldev *global_dev;
800  uint64_t i;
801 
803 
804  M0_LOG(M0_DEBUG, "Targets for key %"PRIu64
805  " (pool dev_id/global dev_id):",
806  be64toh(*(uint64_t *)key->b_addr));
807  M0_LOG(M0_DEBUG, "=============================================");
808  for (i = 0; i < tgts_nr; i++) {
809  global_dev = m0_dix_tgt2sdev(&iter->dit_linst, tgts[i]);
811  "%" PRIu64 "%s: dev_id: %" PRIu64 "/%u",
812  i + 1,
813  tgts_nr > 10 ? (i < 10 ? " " : "") : "",
814  tgts[i],
815  global_dev->pd_sdev_idx);
816  }
817  M0_LOG(M0_DEBUG, "=============================================");
818 }
819 
821  struct m0_poolmach *pm,
822  uint64_t local_dev)
823 {
824  uint64_t unit;
825  uint64_t units_nr;
826  uint64_t tgt;
827  struct m0_pooldev *sdev;
828  bool coord = false;
829 
830  M0_PRE(iter != NULL);
831  M0_PRE(pm != NULL);
832 
833  if (M0_FI_ENABLED("always_coordinator"))
834  return true;
835 
837 
838  unit = 0;
839  /*
840  * Consider only data and parity units. If the first alive unit is spare
841  * then we can not reconstruct parity.
842  */
843  units_nr = m0_dix_liter_N(iter) + m0_dix_liter_K(iter);
844 
845  while (unit < units_nr) {
847 
848  M0_ASSERT(tgt < pm->pm_state->pst_nr_devices);
849 
850  sdev = &pm->pm_state->pst_devices_array[tgt];
851  if (sdev->pd_state != M0_PNDS_ONLINE)
852  unit++;
853  else {
854  coord = sdev->pd_sdev_idx == local_dev;
855  break;
856  }
857  }
858  return coord;
859 }
860 
861 static
863  struct m0_dix_layout_iter *liter,
864  struct m0_poolmach *pm,
865  uint64_t local_device,
866  struct m0_buf *key,
867  bool *is_coordinator,
868  uint64_t **tgts,
869  uint64_t *tgts_nr)
870 {
871  uint64_t unit;
872  uint64_t tgt;
873  uint64_t tgt_tmp;
874  uint64_t units_nr;
875  uint64_t *group_tgts;
876  uint64_t group_tgts_nr;
877  uint32_t N;
878  uint32_t K;
879  struct m0_pooldev *sdev = NULL;
880  int rc = 0;
881 
882  *is_coordinator = false;
883  *tgts = NULL;
884  *tgts_nr = 0;
885 
887 
888  group_tgts_nr = m0_dix_liter_W(liter);
889  M0_ALLOC_ARR(group_tgts, group_tgts_nr);
890  if (group_tgts == NULL)
891  return M0_ERR(-ENOMEM);
892 
893  units_nr = group_tgts_nr;
894 
895  for (unit = 0; unit < units_nr; unit++) {
896  m0_dix_layout_iter_next(liter, &tgt_tmp);
897  group_tgts[unit] = tgt_tmp;
898  }
899 
901 
902  for (unit = 0; unit < units_nr; unit++) {
903  m0_dix_layout_iter_next(liter, &tgt);
904  M0_ASSERT(tgt < pm->pm_state->pst_nr_devices);
905  sdev = &pm->pm_state->pst_devices_array[tgt];
906  if (sdev->pd_sdev_idx == local_device)
907  break;
908  }
909  M0_ASSERT(unit != units_nr);
910  M0_ASSERT(sdev != NULL);
911  M0_ASSERT(sdev->pd_sdev_idx == local_device);
912 
913  N = m0_dix_liter_N(liter);
914  K = m0_dix_liter_K(liter);
915 
916  if (sdev->pd_state == M0_PNDS_ONLINE &&
917  m0_dix_liter_unit_classify(liter, unit) == M0_PUT_SPARE &&
918  pm->pm_state->pst_spare_usage_array[unit - N - K].
920  rc = dix_cm_rebalance_tgts_get(liter, pm,
921  group_tgts, group_tgts_nr,
922  unit - N - K,
923  tgts, tgts_nr);
924  M0_ASSERT(*tgts_nr == 0 || *tgts_nr == 1);
925  if (rc == 0 && *tgts_nr > 0) {
926  M0_ASSERT(*tgts != NULL);
927  *is_coordinator = true;
928  }
929  }
930 
931  if (rc == 0)
932  M0_LOG(M0_DEBUG, "Coordinator? %d, key %"PRIu64,
933  (int)*is_coordinator,
934  be64toh(*(uint64_t *)key->b_addr));
935  m0_free(group_tgts);
936  return M0_RC(rc);
937 }
938 
939 static
941  struct m0_dix_layout_iter *liter,
942  struct m0_poolmach *pm,
943  uint64_t local_device,
944  struct m0_buf *key,
945  bool *is_coordinator,
946  uint64_t **tgts,
947  uint64_t *tgts_nr)
948 {
949  int rc = 0;
950 
951  *is_coordinator = dix_cm_is_repair_coordinator(liter, pm, local_device);
952  M0_LOG(M0_DEBUG, "Coordinator? %d, key %"PRIu64, (int)*is_coordinator,
953  be64toh(*(uint64_t *)key->b_addr));
954 
955  if (*is_coordinator)
956  rc = dix_cm_repair_tgts_get(liter, pm, tgts, tgts_nr);
957 
958  return M0_RC(rc);
959 }
960 
961 static int dix_cm_iter_next_key(struct m0_dix_cm_iter *iter,
962  struct m0_buf *key,
963  struct m0_buf *val,
964  bool *is_coordinator)
965 {
966  struct m0_poolmach *pm;
967  struct m0_fid dix_fid;
968  struct m0_dix_layout layout = {};
969  struct m0_dix_layout_iter layout_iter;
970  uint64_t local_device;
971  struct m0_dix_cm *dix_cm;
972  uint64_t *tgts = NULL;
973  uint64_t tgts_nr = 0;
974  int rc = 0;
975 
976  M0_ENTRY();
977 
978  dix_cm = container_of(iter, struct m0_dix_cm, dcm_it);
979  m0_dix_fid_convert_cctg2dix(&iter->di_cctg_fid, &dix_fid);
980  layout.dl_type = DIX_LTYPE_DESCR;
981  layout.u.dl_desc = iter->di_ldesc;
982  rc = dix_cm_layout_iter_init(&layout_iter, &dix_fid, &layout, dix_cm,
983  key);
984  if (rc != 0)
985  return M0_ERR(rc);
986 
987  pm = dix_cm_pm_get(dix_cm, &layout);
988  local_device = m0_dix_fid_cctg_device_id(&iter->di_cctg_fid);
989 
990  if (M0_FI_ENABLED("print_parity_group")) {
991  parity_group_print(&layout_iter,
992  pm, local_device, key);
993  }
994  if (M0_FI_ENABLED("print_spare_usage")) {
995  spare_usage_print(&layout_iter, pm);
996  }
997 
998  M0_ASSERT(M0_IN(dix_cm->dcm_type, (&dix_repair_dcmt,
999  &dix_rebalance_dcmt)));
1000 
1001  rc = (dix_cm->dcm_type == &dix_repair_dcmt ?
1003  (iter, &layout_iter, pm, local_device, key, is_coordinator,
1004  &tgts, &tgts_nr);
1005 
1006  if (rc == 0 && *is_coordinator && tgts_nr > 0) {
1007  M0_ASSERT(tgts != NULL);
1008 
1009  if (M0_FI_ENABLED("print_targets"))
1010  tgts_print(&layout_iter, tgts, tgts_nr, key);
1011 
1012  iter->di_tgts = tgts;
1013  iter->di_tgts_cur = 0;
1014  iter->di_tgts_nr = tgts_nr;
1015 
1016  rc = dix_cm_iter_buf_copy(&iter->di_key, key,
1017  iter->di_cutoff) ?:
1018  dix_cm_iter_buf_copy(&iter->di_val, val, iter->di_cutoff);
1019  if (rc != 0)
1020  m0_buf_free(&iter->di_key);
1021  }
1022  m0_dix_layout_iter_fini(&layout_iter);
1023 
1024  return M0_RC(rc);
1025 }
1026 
1027 static void dix_cm_iter_meta_unlock(struct m0_dix_cm_iter *iter)
1028 {
1029  iter->di_meta_modified = false;
1031  &iter->di_meta_lock_link);
1032 }
1033 
1034 static int dix_cm_iter_fom_tick(struct m0_fom *fom)
1035 {
1036  struct m0_dix_cm_iter *iter = M0_AMB(iter, fom, di_fom);
1037  struct m0_dix_cm *dix_cm = M0_AMB(dix_cm, iter, dcm_it);
1038  uint8_t min_key = 0;
1039  struct m0_buf kbuf = M0_BUF_INIT(sizeof min_key, &min_key);
1040  struct m0_buf key = {};
1041  struct m0_buf val = {};
1042  int phase = m0_fom_phase(fom);
1043  int result = M0_FSO_AGAIN;
1044  bool is_coordinator = false;
1045  bool is_same_key = false;
1046  struct m0_be_tx *tx;
1047  int rc;
1048 
1049  M0_ENTRY("fom %p, dix_cm %p, phase %d(%s)",
1050  fom, dix_cm, phase, m0_fom_phase_name(fom, phase));
1051 
1052  switch (phase) {
1053  case DIX_ITER_INIT:
1054  dix_cm_iter_init(iter);
1056  result = M0_FSO_WAIT;
1057  break;
1058  case DIX_ITER_STARTED:
1059  if (iter->di_stop)
1061  else
1064  &iter->di_meta_lock_link,
1066  break;
1067  case DIX_ITER_DEL_LOCK:
1069  m0_ctg_del_lock(),
1070  &iter->di_del_lock_link,
1072  break;
1073  case DIX_ITER_CTIDX_START:
1074  case DIX_ITER_CTIDX_REPOS:
1075  if (phase == DIX_ITER_CTIDX_REPOS) {
1077  kbuf = M0_BUF_INIT_PTR(&iter->di_cctg_fid);
1078  }
1079  result = m0_ctg_cursor_get(&iter->di_ctidx_op, &kbuf,
1081  break;
1082  case DIX_ITER_CTIDX_NEXT:
1083  result = m0_ctg_cursor_next(&iter->di_ctidx_op,
1085  break;
1086  case DIX_ITER_NEXT_CCTG:
1087  rc = m0_ctg_op_rc(&iter->di_ctidx_op);
1088  if (rc == 0) {
1089  struct m0_dix_layout *layout;
1090 
1092  iter->di_cctg_fid = *(struct m0_fid *)key.b_addr;
1093  layout = (struct m0_dix_layout *)val.b_addr;
1094  M0_ASSERT(layout->dl_type == DIX_LTYPE_DESCR);
1095  iter->di_ldesc = layout->u.dl_desc;
1096  iter->di_cctg_processed_recs_nr = 0;
1097  }
1099  &iter->di_meta_lock_link);
1100  if (rc == 0) {
1103  &iter->di_meta_lock_link,
1105  } else if (rc == -ENOENT) {
1106  /* No more component catalogues, finish iterator. */
1107  result = dix_cm_iter_eof(iter);
1108  } else {
1109  result = dix_cm_iter_failure(iter, rc);
1110  }
1111  break;
1112  case DIX_ITER_META_LOCK:
1113  /* Lookup component catalogue in meta. */
1114  m0_ctg_op_init(&iter->di_ctg_op, fom, 0);
1115  result = m0_ctg_meta_lookup(&iter->di_ctg_op,
1116  &iter->di_cctg_fid,
1118  if (result < 0)
1119  m0_ctg_op_fini(&iter->di_ctg_op);
1120  break;
1121  case DIX_ITER_CCTG_LOOKUP:
1122  rc = m0_ctg_op_rc(&iter->di_ctg_op);
1123  if (rc == 0)
1125  &iter->di_ctg_op);
1126  else
1127  m0_ctg_op_fini(&iter->di_ctg_op);
1128  if (rc == 0) {
1129  int next_state;
1130 
1131  if (m0_fid_eq(&iter->di_cctg_fid,
1132  &iter->di_prev_cctg_fid)) {
1133  next_state = DIX_ITER_CCTG_CONT;
1134  } else {
1135  next_state = DIX_ITER_CCTG_START;
1136  m0_buf_free(&iter->di_prev_key);
1137  m0_ctg_op_fini(&iter->di_ctg_op);
1138  }
1139 
1140  result = M0_FOM_LONG_LOCK_RETURN(
1142  dix_cm->dcm_type !=
1143  &dix_repair_dcmt,
1144  &iter->di_lock_link, next_state));
1146  } else if (rc == -ENOENT && iter->di_meta_modified) {
1147  /*
1148  * Current component catalogue may be deleted by CAS
1149  * service when iterator had neither catalogue-index
1150  * lock nor meta lock. Go to the next one in this case.
1151  */
1153  result = M0_FOM_LONG_LOCK_RETURN(
1156  &iter->di_meta_lock_link,
1158 
1159  } else {
1161  result = dix_cm_iter_failure(iter, rc);
1162  }
1163  break;
1164  case DIX_ITER_CCTG_START:
1166  m0_ctg_cursor_init(&iter->di_ctg_op, iter->di_cctg);
1167  result = m0_ctg_cursor_get(&iter->di_ctg_op, &kbuf,
1169  if (result < 0) {
1170  m0_ctg_cursor_fini(&iter->di_ctg_op);
1171  m0_ctg_op_fini(&iter->di_ctg_op);
1172  }
1173  break;
1174  case DIX_ITER_CCTG_CONT:
1175  m0_ctg_cursor_init(&iter->di_ctg_op, iter->di_cctg);
1176  result = m0_ctg_cursor_get(&iter->di_ctg_op,
1177  &iter->di_prev_key,
1179  if (result < 0) {
1180  m0_ctg_cursor_fini(&iter->di_ctg_op);
1181  m0_ctg_op_fini(&iter->di_ctg_op);
1182  }
1183  break;
1185  M0_PRE(iter->di_tgts == NULL);
1186  M0_PRE(iter->di_tgts_cur == 0);
1187  M0_PRE(iter->di_tgts_nr == 0);
1188 
1189  result = m0_ctg_cursor_next(&iter->di_ctg_op,
1191  if (result < 0) {
1192  m0_ctg_cursor_fini(&iter->di_ctg_op);
1193  m0_ctg_op_fini(&iter->di_ctg_op);
1194  }
1195  break;
1196  case DIX_ITER_NEXT_KEY:
1197  rc = m0_ctg_op_rc(&iter->di_ctg_op);
1198  if (rc == 0) {
1199  struct m0_buf tmp_key = {};
1200  struct m0_buf tmp_val = {};
1201 
1203  &tmp_key,
1204  &tmp_val);
1205  if (!m0_buf_eq(&iter->di_prev_key, &tmp_key)) {
1206  rc = dix_cm_iter_next_key(iter,
1207  &tmp_key,
1208  &tmp_val,
1209  &is_coordinator);
1210  m0_buf_free(&iter->di_prev_key);
1213  } else
1214  is_same_key = true;
1215  }
1216 
1217  if (rc == 0 && (is_same_key || !is_coordinator ||
1218  iter->di_tgts_nr == 0)) {
1220  result = M0_FSO_AGAIN;
1221  break;
1222  }
1223 
1224  M0_LOG(M0_DEBUG, "%s CM, unlock",
1225  dix_cm->dcm_type == &dix_repair_dcmt ? "Repair" :
1226  "Re-balance");
1228 
1229  if (rc == 0)
1230  result = dix_cm_iter_idle(iter);
1231  else if (rc == -ENOENT) {
1232  /*
1233  * End of current catalogue is reached, lets go to the
1234  * next one.
1235  */
1236  m0_buf_free(&iter->di_prev_key);
1237  m0_ctg_cursor_fini(&iter->di_ctg_op);
1238  m0_ctg_op_fini(&iter->di_ctg_op);
1241  &iter->di_meta_lock_link,
1243  } else
1244  result = dix_cm_iter_failure(iter, rc);
1245  break;
1246  case DIX_ITER_IDLE_START:
1247  M0_ASSERT(iter->di_tgts_cur <= iter->di_tgts_nr);
1248  if (!iter->di_stop && iter->di_tgts_cur < iter->di_tgts_nr) {
1249  /*
1250  * Not all targets are processed for the same key,
1251  * stay on that key.
1252  */
1254  result = M0_FSO_WAIT;
1255  } else {
1256  if (dix_cm->dcm_type == &dix_rebalance_dcmt) {
1257  struct m0_be_tx_credit *accum =
1259  struct m0_be_seg *be_seg =
1261 
1262  iter->di_ctg_del_op_rc = 0;
1263  m0_dtx_init(&fom->fo_tx,
1264  be_seg->bs_domain,
1265  &fom->fo_loc->fl_group);
1267  iter->di_key.b_nob,
1268  iter->di_val.b_nob,
1269  accum);
1270  m0_dtx_open(&fom->fo_tx);
1271  tx = m0_fom_tx(fom);
1274  &fom->fo_cb);
1275  result = M0_FSO_WAIT;
1276  } else
1278  }
1279  break;
1281  M0_ASSERT(dix_cm->dcm_type == &dix_rebalance_dcmt);
1282  tx = m0_fom_tx(fom);
1283  if (m0_be_tx_state(tx) != M0_BTS_ACTIVE) {
1284  if (m0_be_tx_state(tx) == M0_BTS_FAILED)
1285  result = dix_cm_iter_dtx_failure(iter);
1286  else {
1288  &fom->fo_cb);
1289  result = M0_FSO_WAIT;
1290  }
1291  } else {
1292  m0_dtx_opened(&fom->fo_tx);
1293  m0_ctg_op_init(&iter->di_ctg_del_op, fom, 0);
1294  result = m0_ctg_delete(
1295  &iter->di_ctg_del_op,
1296  iter->di_cctg,
1297  &iter->di_key,
1299  }
1300  break;
1301  case DIX_ITER_DEL_TX_WAIT:
1302  M0_ASSERT(dix_cm->dcm_type == &dix_rebalance_dcmt);
1303  iter->di_ctg_del_op_rc =
1304  m0_ctg_op_rc(&iter->di_ctg_del_op);
1305  m0_ctg_op_fini(&iter->di_ctg_del_op);
1306  tx = m0_fom_tx(fom);
1307  if (m0_be_tx_state(tx) == M0_BTS_FAILED) {
1308  M0_ASSERT(iter->di_ctg_del_op_rc != 0);
1309  /* @todo: Can not finalise here in active state. */
1310  fom->fo_tx.tx_state = M0_DTX_DONE;
1311  result = dix_cm_iter_dtx_failure(iter);
1312  } else {
1313  m0_dtx_done(&fom->fo_tx);
1316  &fom->fo_cb);
1317  result = M0_FSO_WAIT;
1318  }
1319  break;
1320  case DIX_ITER_DEL_TX_DONE:
1321  M0_ASSERT(dix_cm->dcm_type == &dix_rebalance_dcmt);
1322  tx = m0_fom_tx(fom);
1323  if (m0_be_tx_state(tx) != M0_BTS_DONE) {
1324  if (m0_be_tx_state(tx) == M0_BTS_FAILED)
1325  result = dix_cm_iter_dtx_failure(iter);
1326  else {
1328  &fom->fo_cb);
1329  result = M0_FSO_WAIT;
1330  }
1331  } else {
1332  dix_cm_iter_dtx_fini(iter);
1333  if (iter->di_ctg_del_op_rc != 0)
1334  result = dix_cm_iter_failure(
1335  iter, iter->di_ctg_del_op_rc);
1336  else
1338  }
1339  break;
1340  case DIX_ITER_IDLE_FIN:
1342  &iter->di_del_lock_link);
1343  iter->di_prev_key = iter->di_key;
1344  M0_SET0(&iter->di_key);
1345  m0_buf_free(&iter->di_val);
1346  dix_cm_iter_tgts_fini(iter);
1347  if (iter->di_stop)
1349  else
1351  m0_ctg_del_lock(),
1352  &iter->di_del_lock_link,
1354  break;
1355  case DIX_ITER_CCTG_CHECK:
1356  if (!iter->di_meta_modified) {
1357  m0_ctg_cursor_fini(&iter->di_ctg_op);
1358  if (dix_cm->dcm_type == &dix_repair_dcmt)
1359  result = M0_FOM_LONG_LOCK_RETURN(
1361  m0_ctg_lock(iter->di_cctg),
1362  &iter->di_lock_link,
1364  else
1365  result = M0_FOM_LONG_LOCK_RETURN(
1367  m0_ctg_lock(iter->di_cctg),
1368  &iter->di_lock_link,
1370  } else {
1371  iter->di_prev_cctg_fid = iter->di_cctg_fid;
1372  m0_ctg_cursor_fini(&iter->di_ctg_op);
1374  result = M0_FOM_LONG_LOCK_RETURN(
1377  &iter->di_meta_lock_link,
1379  }
1380  break;
1381  case DIX_ITER_EOF:
1382  case DIX_ITER_FAILURE:
1383  if (iter->di_stop) {
1384  dix_cm_iter_fini(iter);
1386  }
1387  result = M0_FSO_WAIT;
1388  break;
1389  case DIX_ITER_FINAL:
1390  default:
1391  M0_IMPOSSIBLE("Incorrect phase %d", phase);
1392  }
1393  if (result < 0)
1394  result = dix_cm_iter_failure(iter, result);
1395 
1396  if (result == M0_FSO_WAIT) {
1397  M0_LOG(M0_DEBUG, "iter fom %p current state=%d(%s)",
1398  fom, m0_fom_phase(fom),
1400  }
1401  return M0_RC(result);
1402 }
1403 
1404 static void dix_cm_iter_fom_fini(struct m0_fom *fom)
1405 {
1406  m0_fom_fini(fom);
1407 }
1408 
1409 static const struct m0_fom_ops dix_cm_iter_fom_ops = {
1411  .fo_tick = dix_cm_iter_fom_tick,
1412  .fo_home_locality = dix_cm_iter_fom_locality
1413 };
1414 
1416  .fto_create = NULL
1417 };
1418 
1419 M0_INTERNAL void m0_dix_cm_iter_type_register(struct m0_dix_cm_type *dcmt)
1420 {
1421  uint64_t fom_id;
1422 
1423  fom_id = dcmt->dct_base->ct_fom_id + 4;
1424  m0_fom_type_init(&dcmt->dct_iter_fomt, fom_id,
1427 }
1428 
1429 M0_INTERNAL int m0_dix_cm_iter_start(struct m0_dix_cm_iter *iter,
1430  struct m0_dix_cm_type *dcmt,
1431  struct m0_reqh *reqh,
1432  m0_bcount_t rpc_cutoff)
1433 {
1434  M0_ENTRY("iter = %p", iter);
1435  M0_PRE(M0_IS0(iter));
1436  iter->di_cutoff = rpc_cutoff;
1437  m0_mutex_init(&iter->di_ch_guard);
1438  m0_chan_init(&iter->di_completed, &iter->di_ch_guard);
1440  NULL, NULL, reqh);
1441  m0_fom_queue(&iter->di_fom);
1443  M0_TIME_NEVER);
1444  return M0_RC(0);
1445 }
1446 
1448  struct m0_sm_ast *ast)
1449 {
1450  struct m0_dix_cm_iter *iter = M0_AMB(iter, ast, di_ast);
1451 
1452  M0_PRE(m0_fom_is_waiting(&iter->di_fom));
1453  M0_PRE(M0_IN(m0_fom_phase(&iter->di_fom), (DIX_ITER_STARTED,
1455  m0_fom_wakeup(&iter->di_fom);
1456 }
1457 
1458 M0_INTERNAL void m0_dix_cm_iter_next(struct m0_dix_cm_iter *iter)
1459 {
1461  iter->di_ast.sa_datum = iter;
1462  m0_sm_ast_post(&iter->di_fom.fo_loc->fl_group, &iter->di_ast);
1463 }
1464 
1465 M0_INTERNAL int m0_dix_cm_iter_get(struct m0_dix_cm_iter *iter,
1466  struct m0_buf *key,
1467  struct m0_buf *val,
1468  uint32_t *sdev_id)
1469 {
1470  struct m0_dix_cm *dcm = container_of(iter, struct m0_dix_cm, dcm_it);
1471  struct m0_poolmach *pm;
1472  uint64_t tgt;
1473 
1475  DIX_ITER_EOF,
1476  DIX_ITER_FAILURE)));
1477  if (m0_fom_phase(&iter->di_fom) == DIX_ITER_EOF)
1478  return M0_ERR(-ENODATA);
1479  else if (m0_fom_phase(&iter->di_fom) == DIX_ITER_FAILURE)
1480  return M0_ERR(m0_fom_rc(&iter->di_fom));
1481  else {
1482  int rc;
1483 
1484  M0_ASSERT(iter->di_tgts_cur < iter->di_tgts_nr);
1485 
1486  rc = dix_cm_iter_buf_copy(key, &iter->di_key,
1487  iter->di_cutoff) ?:
1488  dix_cm_iter_buf_copy(val, &iter->di_val, iter->di_cutoff);
1489  if (rc != 0) {
1490  m0_buf_free(key);
1491  } else {
1492  struct m0_dix_layout layout;
1493  struct m0_pooldev *pd;
1494 
1495  layout.dl_type = DIX_LTYPE_DESCR;
1496  layout.u.dl_desc = iter->di_ldesc;
1497  pm = dix_cm_pm_get(dcm, &layout);
1498  M0_ASSERT(pm != NULL);
1499  tgt = iter->di_tgts[iter->di_tgts_cur];
1500  pd = &pm->pm_state->pst_devices_array[tgt];
1501  *sdev_id = pd->pd_sdev_idx;
1502 
1503  M0_CNT_INC(iter->di_tgts_cur);
1504  }
1505 
1506  return M0_RC(rc);
1507  }
1508 }
1509 
1511  struct m0_sm_ast *ast)
1512 {
1513  struct m0_dix_cm_iter *iter = M0_AMB(iter, ast, di_ast);
1514 
1515  iter->di_stop = true;
1516  /*
1517  * Fom is waiting for sure, because AST and FOM state machine execute in
1518  * the same state machine group. But fom executor behaviour can be
1519  * changed in the future, so let's check fom state anyway.
1520  */
1522  m0_fom_wakeup(&iter->di_fom);
1523 }
1524 
1525 M0_INTERNAL void m0_dix_cm_iter_stop(struct m0_dix_cm_iter *iter)
1526 {
1527  M0_ENTRY("iter = %p", iter);
1529  iter->di_ast.sa_datum = iter;
1530  m0_sm_ast_post(&iter->di_fom.fo_loc->fl_group, &iter->di_ast);
1533  m0_mutex_fini(&iter->di_ch_guard);
1534 }
1535 
1536 M0_INTERNAL
1538  struct m0_fid *cctg_fid,
1539  uint64_t *cctg_proc_recs_nr)
1540 {
1541  *cctg_fid = iter->di_cctg_fid;
1542  *cctg_proc_recs_nr = iter->di_cctg_processed_recs_nr;
1543 }
1544 
1545 M0_INTERNAL
1547  uint64_t *proc_recs_nr)
1548 {
1549  *proc_recs_nr = iter->di_processed_recs_nr;
1550 }
1551 
1552 #undef M0_TRACE_SUBSYSTEM
1553 
1556 /*
1557  * Local variables:
1558  * c-indentation-style: "K&R"
1559  * c-basic-offset: 8
1560  * tab-width: 8
1561  * fill-column: 80
1562  * scroll-step: 1
1563  * End:
1564  */
1565 /*
1566  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
1567  */
M0_INTERNAL int m0_buf_copy_aligned(struct m0_buf *dst, const struct m0_buf *src, unsigned shift)
Definition: buf.c:119
static const struct m0_fom_ops dix_cm_iter_fom_ops
Definition: iter.c:1409
static struct m0_sm_state_descr dix_cm_iter_phases[]
Definition: iter.c:71
struct m0_poolmach_state * pm_state
Definition: pool_machine.h:169
M0_INTERNAL void m0_long_lock_link_init(struct m0_long_lock_link *link, struct m0_fom *fom, struct m0_long_lock_addb2 *addb2)
Definition: fom_long_lock.c:66
static void tgts_print(struct m0_dix_layout_iter *iter, uint64_t *tgts, uint64_t tgts_nr, struct m0_buf *key)
Definition: iter.c:794
M0_INTERNAL void m0_ctg_delete_credit(struct m0_cas_ctg *ctg, m0_bcount_t knob, m0_bcount_t vnob, struct m0_be_tx_credit *accum)
Definition: ctg_store.c:1913
struct m0_be_domain * bs_domain
Definition: seg.h:82
M0_INTERNAL void m0_fom_wakeup(struct m0_fom *fom)
Definition: fom.c:532
#define M0_PRE(cond)
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
static void dix_cm_iter_fini(struct m0_dix_cm_iter *iter)
Definition: iter.c:270
M0_INTERNAL void m0_dix_cm_iter_cur_pos(struct m0_dix_cm_iter *iter, struct m0_fid *cctg_fid, uint64_t *cctg_proc_recs_nr)
Definition: iter.c:1537
M0_INTERNAL void m0_dix_fid_convert_cctg2dix(const struct m0_fid *cctg_fid, struct m0_fid *dix_fid)
Definition: fid_convert.c:69
struct m0_buf di_prev_key
Definition: iter.h:97
M0_INTERNAL void m0_chan_broadcast_lock(struct m0_chan *chan)
Definition: chan.c:178
M0_INTERNAL uint32_t m0_dix_liter_K(struct m0_dix_layout_iter *iter)
Definition: layout.c:280
#define M0_FOM_LONG_LOCK_RETURN(rc)
uint64_t ft_id
Definition: fom.h:613
#define NULL
Definition: misc.h:38
M0_INTERNAL void m0_clink_init(struct m0_clink *link, m0_chan_cb_t cb)
Definition: chan.c:201
static struct m0_bufvec dst
Definition: xform.c:61
M0_INTERNAL int m0_ctg_delete(struct m0_ctg_op *ctg_op, struct m0_cas_ctg *ctg, const struct m0_buf *key, int next_phase)
Definition: ctg_store.c:1540
static struct m0_sm_trans_descr dix_cm_iter_trans[]
Definition: iter.c:175
M0_INTERNAL void m0_clink_del_lock(struct m0_clink *link)
Definition: chan.c:293
Definition: idx_mock.c:52
static void dix_cm_iter_next_ast_cb(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: iter.c:1447
void(* sa_cb)(struct m0_sm_group *grp, struct m0_sm_ast *)
Definition: sm.h:506
struct m0_cm_type * dct_base
Definition: cm.h:106
m0_be_tx_state
Definition: tx.h:214
Definition: sm.h:350
const m0_time_t M0_TIME_NEVER
Definition: time.c:108
M0_INTERNAL struct m0_pool_version * m0_pool_version_find(struct m0_pools_common *pc, const struct m0_fid *id)
Definition: pool.c:586
M0_INTERNAL bool m0_buf_eq(const struct m0_buf *x, const struct m0_buf *y)
Definition: buf.c:90
M0_INTERNAL void m0_dix_cm_iter_next(struct m0_dix_cm_iter *iter)
Definition: iter.c:1458
M0_INTERNAL struct m0_long_lock * m0_ctg_lock(struct m0_cas_ctg *ctg)
Definition: ctg_store.c:2162
static struct m0_sm_group * grp
Definition: bytecount.c:38
#define M0_LOG(level,...)
Definition: trace.h:167
M0_LEAVE()
struct m0_clink di_meta_clink
Definition: iter.h:69
static struct m0_be_tx_credit * m0_fom_tx_credit(struct m0_fom *fom)
Definition: fom.h:542
struct m0_sm_group fl_group
Definition: fom.h:274
M0_INTERNAL void m0_sm_ast_post(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: sm.c:135
struct m0_dix_linst dit_linst
Definition: layout.h:135
static bool dix_cm_is_repair_coordinator(struct m0_dix_layout_iter *iter, struct m0_poolmach *pm, uint64_t local_dev)
Definition: iter.c:820
M0_INTERNAL void m0_dtx_init(struct m0_dtx *tx, struct m0_be_domain *be_domain, struct m0_sm_group *sm_group)
Definition: dtm.c:67
static int dix_cm_iter_dtx_failure(struct m0_dix_cm_iter *iter)
Definition: iter.c:315
Definition: cas.h:247
int(* fto_create)(struct m0_fop *fop, struct m0_fom **out, struct m0_reqh *reqh)
Definition: fom.h:650
M0_INTERNAL void m0_dtx_opened(struct m0_dtx *tx)
Definition: dtm.c:94
struct m0_long_lock_addb2 di_meta_lock_addb2
Definition: iter.h:141
static void parity_group_print(struct m0_dix_layout_iter *iter, struct m0_poolmach *pm, uint64_t local_device, struct m0_buf *key)
Definition: iter.c:700
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
struct m0_ctg_op di_ctg_op
Definition: iter.h:108
struct m0_be_chan cc_chan
Definition: ctg_store.h:123
#define m0_exists(var, nr,...)
Definition: misc.h:134
struct m0_fom di_fom
Definition: iter.h:52
static int dix_cm_rebalance_tgts_get(struct m0_dix_layout_iter *iter, struct m0_poolmach *pm, uint64_t *group_tgts, uint64_t group_tgts_nr, uint64_t spare_id, uint64_t **tgts, uint64_t *tgts_nr)
Definition: iter.c:467
M0_INTERNAL void m0_fom_wait_on(struct m0_fom *fom, struct m0_chan *chan, struct m0_fom_callback *cb)
Definition: fom.c:1490
#define M0_BITS(...)
Definition: misc.h:236
uint64_t m0_bcount_t
Definition: types.h:77
M0_INTERNAL void m0_long_write_unlock(struct m0_long_lock *lock, struct m0_long_lock_link *link)
M0_INTERNAL int m0_pageshift_get(void)
Definition: memory.c:238
Definition: sm.h:504
M0_INTERNAL int m0_dix_cm_iter_start(struct m0_dix_cm_iter *iter, struct m0_dix_cm_type *dcmt, struct m0_reqh *reqh, m0_bcount_t rpc_cutoff)
Definition: iter.c:1429
#define container_of(ptr, type, member)
Definition: misc.h:33
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL int m0_ctg_cursor_get(struct m0_ctg_op *ctg_op, const struct m0_buf *key, int next_phase)
Definition: ctg_store.c:1660
struct m0_fid di_prev_cctg_fid
Definition: iter.h:58
#define N(i)
static int dix_cm_repair_tgts_get(struct m0_dix_layout_iter *iter, struct m0_poolmach *pm, uint64_t **tgts, uint64_t *tgts_nr)
Definition: iter.c:566
struct m0_long_lock_link di_meta_lock_link
Definition: iter.h:129
static int dix_cm_iter_fom_tick(struct m0_fom *fom)
Definition: iter.c:1034
m0_fom_phase
Definition: fom.h:372
static int dix_cm_iter_failure(struct m0_dix_cm_iter *iter, int rc)
Definition: iter.c:293
static struct m0_be_tx * m0_fom_tx(struct m0_fom *fom)
Definition: fom.h:537
uint64_t * di_tgts
Definition: iter.h:162
const struct m0_fom_type * fo_type
Definition: dump.c:107
M0_INTERNAL void m0_dix_layout_iter_fini(struct m0_dix_layout_iter *iter)
Definition: layout.c:315
struct m0_pooldev * pst_devices_array
Definition: pool_machine.h:111
return M0_RC(rc)
#define M0_ENTRY(...)
Definition: trace.h:170
struct m0_long_lock_link di_lock_link
Definition: iter.h:123
Definition: buf.h:37
static struct m0_sm_ast ast[NR]
Definition: locality.c:44
static int dix_cm_iter_rebalance_tgts_get(struct m0_dix_cm_iter *iter, struct m0_dix_layout_iter *liter, struct m0_poolmach *pm, uint64_t local_device, struct m0_buf *key, bool *is_coordinator, uint64_t **tgts, uint64_t *tgts_nr)
Definition: iter.c:862
M0_INTERNAL int m0_ctg_cursor_next(struct m0_ctg_op *ctg_op, int next_phase)
Definition: ctg_store.c:1680
M0_INTERNAL int m0_ctg_meta_lookup(struct m0_ctg_op *ctg_op, const struct m0_fid *fid, int next_phase)
Definition: ctg_store.c:1362
uint64_t di_cctg_processed_recs_nr
Definition: iter.h:77
void m0_fom_init(struct m0_fom *fom, const struct m0_fom_type *fom_type, const struct m0_fom_ops *ops, struct m0_fop *fop, struct m0_fop *reply, struct m0_reqh *reqh)
Definition: fom.c:1372
static void dix_cm_iter_stop_ast_cb(struct m0_sm_group *grp, struct m0_sm_ast *ast)
Definition: iter.c:1510
M0_INTERNAL bool m0_long_write_lock(struct m0_long_lock *lk, struct m0_long_lock_link *link, int next_phase)
M0_INTERNAL bool m0_fom_is_waiting(const struct m0_fom *fom)
Definition: fom.c:1732
M0_INTERNAL void m0_ctg_cursor_fini(struct m0_ctg_op *ctg_op)
Definition: ctg_store.c:1749
int i
Definition: dir.c:1033
static int dix_cm_iter_repair_tgts_get(struct m0_dix_cm_iter *iter, struct m0_dix_layout_iter *liter, struct m0_poolmach *pm, uint64_t local_device, struct m0_buf *key, bool *is_coordinator, uint64_t **tgts, uint64_t *tgts_nr)
Definition: iter.c:940
static const struct m0_fom_type_ops dix_cm_iter_fom_type_ops
Definition: iter.c:1415
static int dix_cm_iter_idle(struct m0_dix_cm_iter *iter)
Definition: iter.c:308
#define PRIu64
Definition: types.h:58
struct m0_long_lock_addb2 di_lock_addb2
Definition: iter.h:138
M0_INTERNAL bool m0_long_lock(struct m0_long_lock *lock, bool write, struct m0_long_lock_link *link, int next_phase)
uint32_t pst_nr_spares
Definition: pool_machine.h:120
static void dix_cm_iter_fom_fini(struct m0_fom *fom)
Definition: iter.c:1404
M0_INTERNAL void m0_dix_cm_iter_type_register(struct m0_dix_cm_type *dcmt)
Definition: iter.c:1419
return M0_ERR(-EOPNOTSUPP)
static void dix_cm_iter_tgts_fini(struct m0_dix_cm_iter *iter)
Definition: iter.c:262
static uint64_t dix_cm_iter_fom_locality(const struct m0_fom *fom)
Definition: iter.c:211
void * sa_datum
Definition: sm.h:508
M0_INTERNAL const char * m0_pool_dev_state_to_str(enum m0_pool_nd_state state)
Definition: pool.c:290
#define M0_AMB(obj, ptr, field)
Definition: misc.h:320
M0_INTERNAL void m0_dtx_open(struct m0_dtx *tx)
Definition: dtm.c:86
M0_INTERNAL struct m0_cas_ctg * m0_ctg_meta(void)
Definition: ctg_store.c:2130
M0_INTERNAL void m0_long_unlock(struct m0_long_lock *lock, struct m0_long_lock_link *link)
void m0_fom_fini(struct m0_fom *fom)
Definition: fom.c:1324
M0_EXTERN struct m0_dix_cm_type dix_rebalance_dcmt
Definition: cm.h:176
M0_INTERNAL void m0_chan_init(struct m0_chan *chan, struct m0_mutex *ch_guard)
Definition: chan.c:96
m0_bcount_t b_nob
Definition: buf.h:38
#define M0_ASSERT(cond)
m0_bcount_t di_cutoff
Definition: iter.h:171
const char * scf_name
Definition: sm.h:352
static int dix_cm_tgt_to_unit(uint64_t tgt, uint64_t *group_tgts, uint64_t group_tgts_nr, uint64_t *unit)
Definition: iter.c:363
struct m0_buf di_key
Definition: iter.h:91
M0_INTERNAL void m0_dix_layout_iter_next(struct m0_dix_layout_iter *iter, uint64_t *tgt)
Definition: layout.c:249
static const struct m0_sm_conf dix_cm_iter_sm_conf
Definition: iter.c:192
static struct m0_be_seg * be_seg
Definition: extmap.c:48
struct m0_fid pver
Definition: idx_dix.c:74
M0_INTERNAL void m0_dix_cm_iter_stop(struct m0_dix_cm_iter *iter)
Definition: iter.c:1525
m0_pool_nd_state
Definition: pool_machine.h:57
void m0_fom_phase_move(struct m0_fom *fom, int32_t rc, int phase)
Definition: fom.c:1699
M0_INTERNAL void m0_long_lock_link_fini(struct m0_long_lock_link *link)
Definition: fom_long_lock.c:76
uint64_t ct_fom_id
Definition: cm.h:148
struct m0_chan bch_chan
Definition: format.h:225
uint64_t di_tgts_nr
Definition: iter.h:168
M0_INTERNAL void m0_fom_type_init(struct m0_fom_type *type, uint64_t id, const struct m0_fom_type_ops *ops, const struct m0_reqh_service_type *svc_type, const struct m0_sm_conf *sm)
Definition: fom.c:1596
bool di_stop
Definition: iter.h:150
struct m0_ctg_op di_ctidx_op
Definition: iter.h:103
struct m0_cm dcm_base
Definition: cm.h:119
M0_INTERNAL uint32_t m0_dix_liter_unit_classify(struct m0_dix_layout_iter *iter, uint64_t unit)
Definition: layout.c:295
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
uint32_t pd_sdev_idx
Definition: pool.h:437
M0_INTERNAL void m0_dtx_fini(struct m0_dtx *tx)
Definition: dtm.c:134
M0_EXTERN struct m0_dix_cm_type dix_repair_dcmt
Definition: cm.h:175
Definition: reqh.h:94
M0_INTERNAL uint32_t m0_dix_liter_W(struct m0_dix_layout_iter *iter)
Definition: layout.c:265
struct m0_cas_ctg * di_cctg
Definition: iter.h:72
struct m0_layout_domain rh_ldom
Definition: reqh.h:153
uint32_t dl_type
Definition: layout.h:100
int32_t sm_rc
Definition: sm.h:336
Definition: dump.c:103
uint64_t di_processed_recs_nr
Definition: iter.h:82
M0_INTERNAL uint32_t m0_dix_fid_cctg_device_id(const struct m0_fid *cctg_fid)
Definition: fid_convert.c:81
M0_INTERNAL void m0_buf_free(struct m0_buf *buf)
Definition: buf.c:55
M0_INTERNAL void m0_ctg_cursor_init(struct m0_ctg_op *ctg_op, struct m0_cas_ctg *ctg)
Definition: ctg_store.c:1640
static void dix_cm_iter_init(struct m0_dix_cm_iter *iter)
Definition: iter.c:224
struct m0_dix_ldesc di_ldesc
Definition: iter.h:88
M0_INTERNAL void m0_dtx_done(struct m0_dtx *tx)
Definition: dtm.c:115
union m0_dix_layout::@145 u
Definition: seg.h:66
struct m0_sm t_sm
Definition: tx.h:281
M0_INTERNAL int m0_dix_cm_iter_get(struct m0_dix_cm_iter *iter, struct m0_buf *key, struct m0_buf *val, uint32_t *sdev_id)
Definition: iter.c:1465
M0_INTERNAL int m0_buf_copy(struct m0_buf *dest, const struct m0_buf *src)
Definition: buf.c:104
Definition: cm.h:117
M0_INTERNAL void m0_ctg_op_init(struct m0_ctg_op *ctg_op, struct m0_fom *fom, uint32_t flags)
Definition: ctg_store.c:1759
M0_INTERNAL void m0_dix_layout_iter_reset(struct m0_dix_layout_iter *iter)
Definition: layout.c:310
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
M0_INTERNAL int m0_fom_timedwait(struct m0_fom *fom, uint64_t phases, m0_time_t deadline)
Definition: fom.c:724
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
static bool dix_cm_repair_spare_has_data(struct m0_dix_layout_iter *iter, struct m0_poolmach *pm, uint64_t *group_tgts, uint64_t group_tgts_nr, uint64_t spare_id)
Definition: iter.c:390
Definition: fom.h:481
struct m0_pdclust_tgt_addr tgt
Definition: fd.c:110
struct m0_long_lock_link di_del_lock_link
Definition: iter.h:135
struct m0_mutex di_ch_guard
Definition: iter.h:159
struct m0_reqh reqh
Definition: rm_foms.c:48
M0_INTERNAL void m0_ctg_cursor_kv_get(struct m0_ctg_op *ctg_op, struct m0_buf *key, struct m0_buf *val)
Definition: ctg_store.c:1708
#define M0_BUF_INIT_PTR(p)
Definition: buf.h:69
#define M0_CNT_INC(cnt)
Definition: arith.h:226
#define M0_FI_ENABLED(tag)
Definition: finject.h:231
Definition: fid.h:38
static int dix_cm_iter_eof(struct m0_dix_cm_iter *iter)
Definition: iter.c:301
struct m0_buf di_val
Definition: iter.h:94
struct m0_fom_locality * fo_loc
Definition: fom.h:483
uint32_t psu_device_index
Definition: pool.h:413
#define M0_IS0(obj)
Definition: misc.h:70
struct m0_chan sm_chan
Definition: sm.h:331
struct m0_dix_cm_type * dcm_type
Definition: cm.h:122
struct m0_sm_ast di_ast
Definition: iter.h:147
struct m0_fom_type dct_iter_fomt
Definition: cm.h:107
int di_ctg_del_op_rc
Definition: iter.h:118
struct m0_reqh_service cm_service
Definition: cm.h:191
M0_INTERNAL void m0_dix_layout_iter_goto(struct m0_dix_layout_iter *iter, uint64_t unit)
Definition: layout.c:302
static void dix_cm_iter_dtx_fini(struct m0_dix_cm_iter *iter)
Definition: iter.c:254
struct m0_long_lock_addb2 di_del_lock_addb2
Definition: iter.h:144
M0_INTERNAL uint32_t m0_dix_liter_N(struct m0_dix_layout_iter *iter)
Definition: layout.c:270
bool di_meta_modified
Definition: iter.h:66
M0_INTERNAL int m0_fom_rc(const struct m0_fom *fom)
Definition: fom.c:1727
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL void m0_clink_fini(struct m0_clink *link)
Definition: chan.c:208
struct m0_pools_common * rh_pools
Definition: reqh.h:118
uint32_t psu_device_index
Definition: pool.h:480
uint32_t pst_max_device_failures
Definition: pool_machine.h:126
M0_INTERNAL void m0_rwlock_read_lock(struct m0_rwlock *lock)
Definition: rwlock.c:52
struct m0_be_seg * rh_beseg
Definition: reqh.h:112
M0_INTERNAL void m0_dix_cm_iter_processed_num(struct m0_dix_cm_iter *iter, uint64_t *proc_recs_nr)
Definition: iter.c:1546
struct m0_reqh_service_type ct_stype
Definition: cm.h:145
M0_INTERNAL void m0_fom_queue(struct m0_fom *fom)
Definition: fom.c:624
struct m0_fid di_cctg_fid
Definition: iter.h:55
M0_INTERNAL struct m0_cas_ctg * m0_ctg_ctidx(void)
Definition: ctg_store.c:2135
#define M0_CNT_DEC(cnt)
Definition: arith.h:219
void(* fo_fini)(struct m0_fom *fom)
Definition: fom.h:657
struct m0_ctg_op di_ctg_del_op
Definition: iter.h:113
M0_INTERNAL void m0_ctg_op_fini(struct m0_ctg_op *ctg_op)
Definition: ctg_store.c:1788
static int dix_cm_layout_iter_init(struct m0_dix_layout_iter *iter, const struct m0_fid *index, struct m0_dix_layout *layout, struct m0_dix_cm *dix_cm, struct m0_buf *key)
Definition: iter.c:339
static int dix_cm_iter_buf_copy(struct m0_buf *dst, struct m0_buf *src, m0_bcount_t cutoff)
Definition: iter.c:200
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
M0_INTERNAL void m0_long_read_unlock(struct m0_long_lock *lock, struct m0_long_lock_link *link)
#define out(...)
Definition: gen.c:41
M0_INTERNAL bool m0_long_read_lock(struct m0_long_lock *lk, struct m0_long_lock_link *link, int next_phase)
void m0_fom_phase_set(struct m0_fom *fom, int phase)
Definition: fom.c:1688
uint64_t di_tgts_cur
Definition: iter.h:165
struct m0_reqh * rs_reqh
Definition: reqh_service.h:259
M0_INTERNAL void m0_chan_fini_lock(struct m0_chan *chan)
Definition: chan.c:112
void m0_free(void *data)
Definition: memory.c:146
#define M0_BUF_INIT(size, data)
Definition: buf.h:64
struct m0_pdclust_src_addr src
Definition: fd.c:108
dix_cm_iter_phase
Definition: iter.c:46
static struct m0_poolmach * dix_cm_pm_get(struct m0_dix_cm *dix_cm, struct m0_dix_layout *layout)
Definition: iter.c:324
int32_t rc
Definition: trigger_fop.h:47
struct m0_pool_spare_usage * pst_spare_usage_array
Definition: pool_machine.h:137
struct m0_chan di_completed
Definition: iter.h:156
#define ARRAY_SIZE(a)
Definition: misc.h:45
static void dix_cm_iter_meta_unlock(struct m0_dix_cm_iter *iter)
Definition: iter.c:1027
M0_INTERNAL struct m0_pooldev * m0_dix_tgt2sdev(struct m0_dix_linst *linst, uint64_t tgt)
Definition: layout.c:76
M0_INTERNAL int m0_ctg_op_rc(struct m0_ctg_op *ctg_op)
Definition: ctg_store.c:1779
static int dix_cm_iter_next_key(struct m0_dix_cm_iter *iter, struct m0_buf *key, struct m0_buf *val, bool *is_coordinator)
Definition: iter.c:961
struct m0_dix_cm_iter dcm_it
Definition: cm.h:128
static bool dix_cm_iter_meta_clink_cb(struct m0_clink *cl)
Definition: iter.c:216
M0_INTERNAL struct m0_long_lock * m0_ctg_del_lock(void)
Definition: ctg_store.c:2157
M0_INTERNAL struct m0_reqh * m0_fom_reqh(const struct m0_fom *fom)
Definition: fom.c:283
static void spare_usage_print(struct m0_dix_layout_iter *iter, struct m0_poolmach *pm)
Definition: iter.c:744
Definition: tx.h:280
Definition: idx_mock.c:47
M0_INTERNAL const char * m0_fom_phase_name(const struct m0_fom *fom, int phase)
Definition: fom.c:1722
M0_INTERNAL struct m0_cas_ctg * m0_ctg_meta_lookup_result(struct m0_ctg_op *ctg_op)
Definition: ctg_store.c:1377
#define M0_IMPOSSIBLE(fmt,...)