Motr  M0
iter.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2013-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_SNSCM
24 #include "lib/trace.h"
25 
26 #include "lib/memory.h"
27 #include "lib/assert.h"
28 #include "lib/errno.h"
29 #include "lib/misc.h"
30 #include "lib/finject.h"
31 
32 #include "cob/cob.h"
33 #include "mdstore/mdstore.h"
34 #include "reqh/reqh.h"
35 #include "ioservice/io_service.h"
36 
37 #include "cm/proxy.h"
38 #include "sns/parity_repair.h"
39 #include "sns/cm/cm.h"
40 #include "sns/cm/cp.h"
41 #include "sns/cm/ag.h"
42 #include "sns/cm/cm_utils.h"
43 #include "sns/cm/file.h"
44 #include "ioservice/fid_convert.h" /* m0_fid_gob_make */
45 
52 enum {
53  SNS_REPAIR_ITER_MAGIX = 0x33BAADF00DCAFE77,
54 };
55 
56 static const struct m0_bob_type iter_bob = {
57  .bt_name = "sns cm data iterator",
58  .bt_magix_offset = M0_MAGIX_OFFSET(struct m0_sns_cm_iter, si_magix),
59  .bt_magix = SNS_REPAIR_ITER_MAGIX,
60  .bt_check = NULL
61 };
62 
64 
117 };
118 
119 M0_INTERNAL struct m0_sns_cm *it2sns(struct m0_sns_cm_iter *it)
120 {
121  return container_of(it, struct m0_sns_cm, sc_it);
122 }
123 
127 static enum cm_data_iter_phase iter_phase(const struct m0_sns_cm_iter *it)
128 {
129  return it->si_sm.sm_state;
130 }
131 
135 static void iter_phase_set(struct m0_sns_cm_iter *it, int phase)
136 {
137  m0_sm_state_set(&it->si_sm, phase);
138 }
139 
140 static bool
142  const struct m0_sns_cm_iter_file_ctx *ifc)
143 {
144  struct m0_pdclust_layout *pl =
146 
147  return ergo(M0_IN(phase, (ITPH_COB_NEXT, ITPH_GROUP_NEXT,
148  ITPH_CP_SETUP)),
149  pl != NULL &&
150  ifc->ifc_fctx->sf_pi != NULL && ifc->ifc_upg != 0 &&
151  ifc->ifc_dpupg != 0 && m0_fid_is_set(&ifc->ifc_gfid)) &&
152  ergo(M0_IN(phase, (ITPH_CP_SETUP)), ifc->ifc_group_last >= 0 &&
153  m0_fid_is_set(&ifc->ifc_cob_fid) &&
154  ifc->ifc_sa.sa_group <= ifc->ifc_group_last &&
155  ifc->ifc_sa.sa_unit <= ifc->ifc_upg &&
156  ifc->ifc_ta.ta_obj <= m0_pdclust_P(pl));
157 }
158 
159 static bool iter_invariant(const struct m0_sns_cm_iter *it)
160 {
161  return it != NULL && m0_sns_cm_iter_bob_check(it) &&
162  it->si_cp != NULL &&
163  ergo(it->si_fc.ifc_fctx != NULL &&
164  it->si_fc.ifc_fctx->sf_layout != NULL,
166 }
167 
173 static void unit_to_cobfid(struct m0_sns_cm_iter_file_ctx *ifc,
174  struct m0_fid *cob_fid_out)
175 {
176  struct m0_pdclust_src_addr *sa;
177  struct m0_pdclust_tgt_addr *ta;
178 
179  sa = &ifc->ifc_sa;
180  ta = &ifc->ifc_ta;
182  sa->sa_group,
183  sa->sa_unit);
184  m0_sns_cm_unit2cobfid(ifc->ifc_fctx, sa, ta, cob_fid_out);
185 }
186 
187 /* Uses name space iterator. */
188 M0_INTERNAL int __fid_next(struct m0_sns_cm_iter *it, struct m0_fid *fid_next)
189 {
190  struct m0_sns_cm_iter_file_ctx *ifc = &it->si_fc;
191  struct m0_cob_nsrec *nsrec;
192  struct m0_pool_version *pv;
193  struct m0_sns_cm *scm = it2sns(it);
194  struct m0_reqh *reqh = m0_sns_cm2reqh(scm);
195  int rc;
196 
197  M0_ENTRY("it = %p", it);
198 
199  rc = m0_cob_ns_iter_next(&it->si_cns_it, fid_next, &nsrec);
200  if (rc == 0) {
202  ifc->ifc_pm = &pv->pv_mach;
203  }
204 
205  return M0_RC(rc);
206 }
207 
209 {
210  struct m0_sns_cm *scm = it2sns(it);
211  struct m0_cm *cm = &scm->sc_base;
212  struct m0_pdclust_layout *pl;
213  struct m0_cm_ag_id *out_last;
214  struct m0_sns_cm_file_ctx *fctx = it->si_fc.ifc_fctx;
215 
216  pl = m0_layout_to_pdl(it->si_fc.ifc_fctx->sf_layout);
217  if (pl == NULL)
218  return M0_RC(M0_FSO_WAIT);
219 
220  /*
221  * We need only the number of parity units equivalent
222  * to the number of failures.
223  */
224  it->si_fc.ifc_dpupg = m0_sns_cm_ag_nr_data_units(pl) +
226  it->si_fc.ifc_upg = m0_sns_cm_ag_size(pl);
227  M0_CNT_INC(it->si_total_files);
228  out_last = &cm->cm_last_processed_out;
229  if (m0_cm_ag_id_is_set(out_last)) {
230  it->si_fc.ifc_sa.sa_group = agid2group(out_last);
231  } else
232  it->si_fc.ifc_sa.sa_group = 0;
233 
234  it->si_fc.ifc_sa.sa_unit = 0;
235  it->si_ag = NULL;
236  M0_SET0(out_last);
237  it->si_fc.ifc_group_last = fctx->sf_max_group;
238 
239  return M0_RC(0);
240 }
241 
242 static int group__next(struct m0_sns_cm_iter *it)
243 {
244  int rc;
245 
247  if (rc == 0)
249  return M0_RC(rc);
250 }
251 
254 {
255  struct m0_sns_cm_file_ctx *fctx = it->si_fc.ifc_fctx;
256  int rc;
257 
258  M0_PRE(fctx != NULL);
259 
260  fctx->sf_pm = it->si_fc.ifc_pm;
262  if (rc == 0) {
263  M0_ASSERT(fctx->sf_pi != NULL);
264  rc = group__next(it);
265  M0_ASSERT(fctx->sf_pi != NULL);
266  }
267  if (rc == -EAGAIN) {
269  return M0_RC(M0_FSO_WAIT);
270  }
271 
272  if (rc == -ENOENT) {
274  rc = 0;
275  }
276 
277  return M0_RC(rc);
278 }
279 
280 static int iter_fid_lock(struct m0_sns_cm_iter *it)
281 {
282  struct m0_sns_cm *scm;
283  struct m0_fid *fid;
284  int rc = 0;
285 
286  M0_ENTRY();
287  M0_PRE(it != NULL);
288 
289  scm = it2sns(it);
290  fid = &it->si_fc.ifc_gfid;
292  rc = m0_sns_cm_file_lock(scm, fid, &it->si_fc.ifc_fctx);
293  if (rc == 0)
295  if (rc == -EAGAIN) {
297  rc = 0;
298  }
300  return M0_RC(rc);
301 }
302 
304 {
305  struct m0_sns_cm *scm;
306  int rc = 0;
307  struct m0_sns_cm_file_ctx *fctx;
308 
309  M0_ENTRY();
310  M0_PRE(it != NULL);
311 
312  scm = it2sns(it);
313  fctx = it->si_fc.ifc_fctx;
315  rc = m0_sns_cm_file_lock_wait(fctx, it->si_fom);
316  if (rc == -EAGAIN) {
317  rc = M0_FSO_WAIT;
318  goto end;
319  }
320  if (rc == 0)
322 
323 end:
325  return M0_RC(rc);
326 }
327 
329 static int iter_fid_next(struct m0_sns_cm_iter *it)
330 {
331  struct m0_sns_cm_iter_file_ctx *ifc = &it->si_fc;
332  struct m0_fid fid_next;
333  int rc;
334  M0_ENTRY("it = %p", it);
335 
336  m0_fid_gob_make(&fid_next, 0, 0);
337  ifc->ifc_fctx = NULL;
338 
339  /* Get current GOB fid saved in the iterator. */
340  do {
341  rc = __fid_next(it, &fid_next);
342  } while (rc == 0 && (m0_fid_eq(&fid_next, &M0_COB_ROOT_FID) ||
343  m0_fid_eq(&fid_next, &M0_MDSERVICE_SLASH_FID)));
344  if (rc == 0) {
345  /* Save next GOB fid in the iterator. */
346  ifc->ifc_gfid = fid_next;
347  }
348  /* fini old layout instance and put old layout */
349  if (ifc->ifc_fctx != NULL && ifc->ifc_fctx->sf_layout != NULL) {
350  if (M0_FI_ENABLED("ut_fid_next"))
352  }
353  if (rc == -ENOENT) {
354  M0_LOG(M0_DEBUG, "no more data: returning -ENODATA last fid"
355  FID_F, FID_P(&ifc->ifc_gfid));
356  return M0_RC(-ENODATA);
357  }
358 
360  return M0_RC(rc);
361 }
362 
363 static bool __has_incoming(struct m0_sns_cm *scm,
364  struct m0_sns_cm_file_ctx *fctx, uint64_t group)
365 {
366  struct m0_cm_ag_id agid;
367 
368  M0_PRE(scm != NULL && fctx != NULL);
369 
371  M0_LOG(M0_DEBUG, "agid [%" PRId64 "] [%" PRId64 "] [%" PRId64 "] [%" PRId64 "]",
372  agid.ai_hi.u_hi, agid.ai_hi.u_lo,
373  agid.ai_lo.u_hi, agid.ai_lo.u_lo);
374  return m0_sns_cm_ag_is_relevant(scm, fctx, &agid);
375 }
376 
377 
378 static bool __group_skip(struct m0_sns_cm_iter *it, uint64_t group)
379 {
380  struct m0_sns_cm_iter_file_ctx *ifc = &it->si_fc;
381  struct m0_sns_cm_file_ctx *fctx = ifc->ifc_fctx;
382  struct m0_fid cobfid;
383  struct m0_pdclust_src_addr sa;
384  struct m0_pdclust_tgt_addr ta;
385  int i;
386  struct m0_poolmach *pm = fctx->sf_pm;
387  struct m0_sns_cm *scm = it2sns(it);
388 
389  M0_ENTRY("it: %p group: %lu", it, (unsigned long)group);
390 
391  for (i = 0; i < ifc->ifc_upg; ++i) {
392  sa.sa_unit = i;
393  sa.sa_group = group;
394  m0_sns_cm_unit2cobfid(fctx, &sa, &ta, &cobfid);
395  if (scm->sc_helpers->sch_is_cob_failed(pm, ta.ta_obj) &&
398  return false;
399  }
400 
401  return true;
402 }
403 
404 
405 static int __group_alloc(struct m0_sns_cm *scm, struct m0_fid *gfid,
406  uint64_t group, struct m0_pdclust_layout *pl,
407  bool has_incoming, struct m0_cm_aggr_group **ag)
408 {
409  struct m0_cm *cm = &scm->sc_base;
410  struct m0_cm_ag_id agid;
411  size_t nr_bufs;
412  int rc = 0;
413 
415  /*
416  * Allocate new aggregation group for the given aggregation
417  * group identifier.
418  * Check if the aggregation group has incoming copy packets, if
419  * yes, check if the aggregation group was already created and
420  * processed through sliding window.
421  * Thus if sliding_window_lo < agid < sliding_window_hi then the
422  * group was already processed and we proceed to next group.
423  */
424  if (has_incoming) {
425  if (m0_cm_ag_id_cmp(&agid,
426  &cm->cm_sw_last_updated_hi) <= 0) {
427  *ag = m0_cm_aggr_group_locate(cm, &agid, has_incoming);
428  /* SNS repair abort or quiesce ca lead to frozen
429  * aggregation groups. It is possible that the
430  * aggregation group was detected frozen in such
431  * incident and was finalised. In regular sns operation
432  * this situation is not expected.
433  */
434  if (*ag == NULL) {
435  M0_LOG(M0_DEBUG, "group "M0_AG_F" not found",
436  M0_AG_P(&agid));
437  rc = -ENOENT;
438  }
439  goto out;
440  }
441  }
442 
443  if (has_incoming) {
444  rc = cm->cm_ops->cmo_get_space_for(cm, &agid, &nr_bufs);
445  if (rc == 0)
447  M0_LOG(M0_DEBUG, "agid [%" PRId64 "] [%" PRId64 "] "
448  "[%" PRId64 "] [%" PRId64 "]",
449  agid.ai_hi.u_hi, agid.ai_hi.u_lo,
450  agid.ai_lo.u_hi, agid.ai_lo.u_lo);
451  }
452  if (rc == 0) {
453  rc = m0_cm_aggr_group_alloc(cm, &agid, has_incoming, ag);
454  if (rc != 0 && has_incoming)
456  }
457 
458 out:
459  if (*ag != NULL && has_incoming) {
460  if ((*ag)->cag_cp_local_nr > 0 &&
461  !aggr_grps_out_tlink_is_in(*ag))
462  m0_cm_aggr_group_add(cm, *ag, false);
463  }
464  return M0_RC(rc);
465 }
466 
474 static int __group_next(struct m0_sns_cm_iter *it)
475 {
476  struct m0_sns_cm *scm = it2sns(it);
477  struct m0_sns_cm_iter_file_ctx *ifc;
478  struct m0_sns_cm_file_ctx *fctx;
479  struct m0_pdclust_src_addr *sa;
480  struct m0_fid *gfid;
481  struct m0_pdclust_layout *pl;
482  uint64_t group;
483  uint64_t nrlu = 0;
484  bool has_incoming = false;
485  int rc = 0;
486  struct m0_poolmach *pm;
487 
488  M0_ENTRY("it = %p", it);
489 
490  ifc = &it->si_fc;
491  fctx = ifc->ifc_fctx;
493  sa = &ifc->ifc_sa;
494  gfid = &ifc->ifc_gfid;
495  if (it->si_ag != NULL)
496  m0_cm_ag_put(it->si_ag);
497  it->si_ag = NULL;
498  pm = fctx->sf_pm;
500  goto fid_next;
501  for (group = sa->sa_group; group <= ifc->ifc_group_last; ++group) {
502  if (__group_skip(it, group))
503  continue;
504  has_incoming = __has_incoming(scm, ifc->ifc_fctx, group);
505  if (!has_incoming)
507  group);
508  if (has_incoming || nrlu > 0) {
509  rc = __group_alloc(scm, gfid, group, pl, has_incoming,
510  &it->si_ag);
511  if (rc == -ENOENT) {
512  rc = 0;
513  continue;
514  }
515  if (it->si_ag != NULL)
516  m0_cm_ag_get(it->si_ag);
517  if (rc != 0) {
518  if (rc == -ENOBUFS)
520  if (rc == -EINVAL) {
522  rc = 0;
523  goto fid_next;
524  }
525  if (M0_IN(rc, (-ENOENT, -ESHUTDOWN))) {
526  rc = 0;
527  continue;
528  }
529  }
530  ifc->ifc_sa.sa_group = group;
531  ifc->ifc_sa.sa_unit = 0;
532  if (rc == 0)
534  goto out;
535  }
536  }
537 
538 fid_next:
539  /* Put the reference on the file lock taken in ITPH_FID_NEXT phase. */
543  it->si_fc.ifc_fctx = NULL;
545 out:
546  return M0_RC(rc);
547 }
548 
554 static int iter_group_next(struct m0_sns_cm_iter *it)
555 {
556  return __group_next(it);
557 }
558 
567 static int iter_ag_setup(struct m0_sns_cm_iter *it)
568 {
569  struct m0_sns_cm *scm = it2sns(it);
570  struct m0_cm_aggr_group *ag;
571  struct m0_sns_cm_ag *sag;
572  struct m0_sns_cm_file_ctx *fctx;
573  struct m0_pdclust_layout *pl;
574  int rc;
575 
576  fctx = it->si_fc.ifc_fctx;
578  ag = it->si_ag;
579  M0_ASSERT(ag != NULL);
580  sag = ag2snsag(ag);
581  rc = scm->sc_helpers->sch_ag_setup(sag, pl);
582  if (rc == 0)
584 
585  return M0_RC(rc);
586 }
587 
588 static bool unit_has_data(struct m0_sns_cm *scm, uint32_t unit)
589 {
590  struct m0_sns_cm_iter_file_ctx *ifc = &scm->sc_it.si_fc;
591  struct m0_pdclust_layout *pl;
592  enum m0_cm_op op = scm->sc_op;
593 
594  pl = m0_layout_to_pdl(ifc->ifc_fctx->sf_layout);
595  switch(op) {
596  case CM_OP_REPAIR:
597  return !ifc->ifc_cob_is_spare_unit;
598  case CM_OP_REBALANCE:
599  if (m0_pdclust_unit_classify(pl, unit) == M0_PUT_SPARE)
600  return !ifc->ifc_cob_is_spare_unit;
601  break;
602  default:
603  M0_IMPOSSIBLE("Bad operation");
604  }
605 
606  return false;
607 }
608 
612 static int iter_cp_setup(struct m0_sns_cm_iter *it)
613 {
614  struct m0_sns_cm *scm = it2sns(it);
615  struct m0_pdclust_layout *pl;
616  struct m0_sns_cm_iter_file_ctx *ifc;
617  struct m0_sns_cm_file_ctx *fctx;
618  struct m0_sns_cm_cp *scp;
619  struct m0_sns_cm_ag *sag;
620  bool has_data;
621  uint64_t group;
622  uint64_t stob_offset;
623  uint64_t cp_data_seg_nr;
624  uint64_t ag_cp_idx;
625  int rc = 0;
626 
627  M0_ENTRY("it = %p", it);
628 
629  ifc = &it->si_fc;
630  fctx = ifc->ifc_fctx;
632  group = ifc->ifc_sa.sa_group;
633  has_data = unit_has_data(scm, ifc->ifc_sa.sa_unit - 1);
634  if (!has_data)
635  goto out;
636  stob_offset = ifc->ifc_ta.ta_frame *
638  scp = it->si_cp;
639  if (scp->sc_base.c_ag == NULL)
640  m0_cm_ag_cp_add(it->si_ag, &scp->sc_base);
642  scp->sc_is_local = true;
643  cp_data_seg_nr = m0_sns_cm_data_seg_nr(scm, pl);
644  /*
645  * ifc->ifc_sa.sa_unit has gotten one index ahead. Hence actual
646  * index of the copy packet is (ifc->ifc_sa.sa_unit - 1).
647  * see iter_cob_next().
648  */
649  ag_cp_idx = ifc->ifc_sa.sa_unit - 1;
650  /*
651  * If the aggregation group unit to be read is a spare unit
652  * containing data then map the spare unit to its corresponding
653  * failed data/parity unit in the aggregation group @ag.
654  * This is required to mark the appropriate data/parity unit of
655  * which this spare contains data.
656  */
657 
658  if (m0_pdclust_unit_classify(pl, ag_cp_idx) == M0_PUT_SPARE) {
661  fctx->sf_pi, group,
662  ag_cp_idx, &ag_cp_idx);
664  if (rc != 0)
665  return M0_RC(rc);
666  }
667  rc = m0_sns_cm_cp_setup(scp, &ifc->ifc_cob_fid, stob_offset,
668  cp_data_seg_nr, ~0, ag_cp_idx);
669  if (rc < 0)
670  return M0_RC(rc);
671 
673  rc = M0_FSO_AGAIN;
674 out:
676  return M0_RC(rc);
677 }
678 
690 static int iter_cob_next(struct m0_sns_cm_iter *it)
691 {
692  struct m0_sns_cm_iter_file_ctx *ifc;
693  struct m0_fid *cob_fid;
694  struct m0_pdclust_src_addr *sa;
695  struct m0_sns_cm *scm;
697 
698  M0_ENTRY("it=%p", it);
699 
700  ifc = &it->si_fc;
701  sa = &ifc->ifc_sa;
702  scm = it2sns(it);
703  cob_fid = &ifc->ifc_cob_fid;
704  it->si_cp->sc_is_hole_eof = false;
705 
706  do {
707  if (sa->sa_unit >= ifc->ifc_upg) {
708  ++sa->sa_group;
710  return M0_RC(0);
711  }
712  /*
713  * Calculate COB fid corresponding to the unit and advance
714  * scm->sc_it.si_src::sa_unit to next unit in the parity
715  * group. If this is the last unit in the parity group then
716  * proceed to next parity group in the GOB.
717  */
718  unit_to_cobfid(ifc, cob_fid);
720  sa->sa_unit);
721  ++sa->sa_unit;
722  } while (ut == M0_SNS_CM_UNIT_INVALID ||
724  ifc->ifc_ta.ta_obj));
725 
726  if (ut == M0_SNS_CM_UNIT_HOLE_EOF)
727  it->si_cp->sc_is_hole_eof = true;
728 
731 
732  return M0_RC(0);
733 }
734 
739 M0_INTERNAL int iter_idle(struct m0_sns_cm_iter *it)
740 {
742 
743  return 0;
744 }
745 
746 static int (*iter_action[])(struct m0_sns_cm_iter *it) = {
747  [ITPH_IDLE] = iter_idle,
756 };
757 
762 M0_INTERNAL int m0_sns_cm_iter_next(struct m0_cm *cm, struct m0_cm_cp *cp)
763 {
764  struct m0_sns_cm *scm;
765  struct m0_sns_cm_iter *it;
766  int rc;
767  M0_ENTRY("cm = %p, cp = %p", cm, cp);
768 
769  M0_PRE(cm != NULL && cp != NULL);
770 
771  scm = cm2sns(cm);
772  it = &scm->sc_it;
773  it->si_cp = cp2snscp(cp);
774  do {
775  if (cm->cm_quiesce || cm->cm_abort) {
776  if (M0_IN(iter_phase(it), (ITPH_FID_NEXT,
777  ITPH_GROUP_NEXT))) {
778  M0_LOG(M0_DEBUG, "%" PRId64 ": "
779  "Got %s cmd: returning -ENODATA",
780  cm->cm_id,
781  cm->cm_quiesce ? "QUIESCE" : "ABORT");
782  if (iter_phase(it) == ITPH_GROUP_NEXT &&
783  it->si_ag != NULL)
784  m0_cm_ag_put(it->si_ag);
785 
786  return M0_RC(-ENODATA);
787  }
788  }
791  } while (rc == 0);
792 
793  if (rc == -ENODATA)
795 
796  if (M0_IN(rc, (-ENOBUFS, -ENOSPC))) {
797  m0_sns_cm_buf_wait(rc == -ENOSPC ? &scm->sc_ibp : &scm->sc_obp,
798  it->si_fom);
799  rc = -ENOBUFS;
800  }
801 
802  return M0_RC(rc);
803 }
804 
806  [ITPH_INIT] = {
808  .sd_name = "iter init",
809  .sd_allowed = M0_BITS(ITPH_IDLE, ITPH_FINI)
810  },
811  [ITPH_IDLE] = {
812  .sd_flags = 0,
813  .sd_name = "iter idle",
814  .sd_allowed = M0_BITS(ITPH_FID_NEXT, ITPH_FINI)
815  },
816  [ITPH_COB_NEXT] = {
817  .sd_flags = 0,
818  .sd_name = "COB next",
820  },
821  [ITPH_GROUP_NEXT] = {
822  .sd_flags = 0,
823  .sd_name = "group next",
824  .sd_allowed = M0_BITS(ITPH_COB_NEXT, ITPH_AG_SETUP,
826  },
827  [ITPH_FID_NEXT] = {
828  .sd_flags = 0,
829  .sd_name = "FID next",
830  .sd_allowed = M0_BITS(ITPH_GROUP_NEXT, ITPH_FID_LOCK,
831  ITPH_IDLE)
832  },
833  [ITPH_FID_LOCK] = {
834  .sd_flags = 0,
835  .sd_name = "File lock wait",
837  },
838  [ITPH_FID_LOCK_WAIT] = {
839  .sd_flags = 0,
840  .sd_name = "File lock wait",
841  .sd_allowed = M0_BITS(ITPH_FID_ATTR_LAYOUT)
842  },
844  .sd_flags = 0,
845  .sd_name = "File attr and layout fetch",
847  },
848  [ITPH_CP_SETUP] = {
849  .sd_flags = 0,
850  .sd_name = "cp setup",
851  .sd_allowed = M0_BITS(ITPH_COB_NEXT)
852  },
853  [ITPH_AG_SETUP] = {
854  .sd_flags = 0,
855  .sd_name = "ag setup",
856  .sd_allowed = M0_BITS(ITPH_COB_NEXT)
857  },
858  [ITPH_FINI] = {
859  .sd_flags = M0_SDF_TERMINAL,
860  .sd_name = "cm iter fini",
861  .sd_allowed = 0
862  }
863 };
864 
865 static const struct m0_sm_conf cm_iter_sm_conf = {
866  .scf_name = "sm: cm_iter_conf",
867  .scf_nr_states = ARRAY_SIZE(cm_iter_sd),
868  .scf_state = cm_iter_sd
869 };
870 
871 M0_INTERNAL int m0_sns_cm_iter_init(struct m0_sns_cm_iter *it)
872 {
873  struct m0_sns_cm *scm = it2sns(it);
874  struct m0_cm *cm;
875 
876  M0_PRE(it != NULL);
877 
878  cm = &scm->sc_base;
880  m0_sns_cm_iter_bob_init(it);
881  it->si_total_files = 0;
882  if (it->si_fom == NULL)
883  it->si_fom = &scm->sc_base.cm_cp_pump.p_fom;
884 
885  return M0_RC(0);
886 }
887 
888 M0_INTERNAL int m0_sns_cm_iter_start(struct m0_sns_cm_iter *it)
889 {
890  struct m0_fid gfid;
891  struct m0_fid gfid_start;
892  struct m0_sns_cm *scm = it2sns(it);
893  struct m0_cm *cm = &scm->sc_base;
894  int rc;
895 
896  M0_PRE(it != NULL);
897  M0_PRE(M0_IN(iter_phase(it), (ITPH_INIT, ITPH_IDLE)));
898 
899  agid2fid(&cm->cm_last_processed_out, &gfid_start);
900  m0_fid_gob_make(&gfid, gfid_start.f_container, gfid_start.f_key);
901  rc = m0_cob_ns_iter_init(&it->si_cns_it, &gfid, scm->sc_cob_dom);
902  if (iter_phase(it) == ITPH_INIT)
904 
905  return M0_RC(rc);
906 }
907 
908 M0_INTERNAL void m0_sns_cm_iter_stop(struct m0_sns_cm_iter *it)
909 {
912 
913  if (!M0_IN(iter_phase(it), (ITPH_INIT, ITPH_IDLE)))
915  if (iter_phase(it) == ITPH_IDLE) {
916  if (it->si_cns_it.cni_cdom != NULL)
917  m0_cob_ns_iter_fini(&it->si_cns_it);
918  M0_SET0(&it->si_fc);
919  }
920 }
921 
922 M0_INTERNAL void m0_sns_cm_iter_fini(struct m0_sns_cm_iter *it)
923 {
924  M0_PRE(it != NULL);
925  M0_PRE(M0_IN(iter_phase(it), (ITPH_INIT, ITPH_IDLE)));
926 
928  m0_sm_fini(&it->si_sm);
929  m0_sns_cm_iter_bob_fini(it);
930 }
931 
933 #undef M0_TRACE_SUBSYSTEM
934 
935 /*
936  * Local variables:
937  * c-indentation-style: "K&R"
938  * c-basic-offset: 8
939  * tab-width: 8
940  * fill-column: 80
941  * scroll-step: 1
942  * End:
943  */
M0_INTERNAL void m0_sns_cm_pver_dirty_set(struct m0_pool_version *pver)
Definition: cm_utils.c:580
M0_INTERNAL uint64_t m0_sns_cm_ag_nr_data_units(const struct m0_pdclust_layout *pl)
Definition: cm_utils.c:222
M0_INTERNAL bool m0_sns_cm_ag_is_relevant(struct m0_sns_cm *scm, struct m0_sns_cm_file_ctx *fctx, const struct m0_cm_ag_id *id)
Definition: cm_utils.c:505
Definition: cm.h:205
static const struct m0_bob_type iter_bob
Definition: iter.c:56
static int iter_ag_setup(struct m0_sns_cm_iter *it)
Definition: iter.c:567
int(* cmo_get_space_for)(struct m0_cm *cm, const struct m0_cm_ag_id *id, size_t *count)
Definition: cm.h:335
M0_INTERNAL void m0_cm_ag_get(struct m0_cm_aggr_group *ag)
Definition: ag.c:488
#define M0_PRE(cond)
M0_INTERNAL void m0_sns_cm_unit2cobfid(struct m0_sns_cm_file_ctx *fctx, const struct m0_pdclust_src_addr *sa, struct m0_pdclust_tgt_addr *ta, struct m0_fid *cfid_out)
Definition: cm_utils.c:117
M0_INTERNAL bool m0_sns_cm_pver_is_dirty(struct m0_pool_version *pver)
Definition: cm_utils.c:575
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
M0_INTERNAL void m0_fid_gob_make(struct m0_fid *gob_fid, uint32_t container, uint64_t key)
Definition: fid_convert.c:46
uint64_t sa_group
Definition: pdclust.h:241
M0_INTERNAL void agid2fid(const struct m0_cm_ag_id *id, struct m0_fid *fid)
Definition: ag.c:405
struct m0_sns_cm_buf_pool sc_obp
Definition: cm.h:240
#define NULL
Definition: misc.h:38
#define M0_AG_P(ag)
Definition: ag.h:55
static bool __has_incoming(struct m0_sns_cm *scm, struct m0_sns_cm_file_ctx *fctx, uint64_t group)
Definition: iter.c:363
M0_INTERNAL struct m0_sns_cm * it2sns(struct m0_sns_cm_iter *it)
Definition: iter.c:119
M0_INTERNAL struct m0_sns_cm * cm2sns(struct m0_cm *cm)
Definition: cm.c:389
struct m0_fid ifc_cob_fid
Definition: iter.h:83
#define ergo(a, b)
Definition: misc.h:293
static int iter_fid_attr_layout(struct m0_sns_cm_iter *it)
Definition: iter.c:253
M0_INTERNAL int m0_cob_ns_iter_next(struct m0_cob_fid_ns_iter *iter, struct m0_fid *gfid, struct m0_cob_nsrec **nsrec)
Definition: ns_iter.c:100
struct m0_sns_cm_file_ctx * ifc_fctx
Definition: iter.h:53
bool cm_quiesce
Definition: cm.h:277
struct m0_poolmach * ifc_pm
Definition: iter.h:58
const struct m0_cm_ops * cm_ops
Definition: cm.h:188
Definition: sm.h:350
M0_INTERNAL void m0_sns_cm_iter_stop(struct m0_sns_cm_iter *it)
Definition: iter.c:908
struct m0_pool_version * pm_pver
Definition: pool_machine.h:172
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 void m0_cm_aggr_group_add(struct m0_cm *cm, struct m0_cm_aggr_group *ag, bool has_incoming)
Definition: ag.c:301
struct m0_pool_version * pv
Definition: dir.c:629
struct m0_poolmach pv_mach
Definition: pool.h:133
#define M0_LOG(level,...)
Definition: trace.h:167
Definition: cp.h:160
uint64_t cm_id
Definition: cm.h:174
M0_INTERNAL void m0_sns_cm_ag_agid_setup(const struct m0_fid *gob_fid, uint64_t group, struct m0_cm_ag_id *agid)
Definition: ag.c:396
static int __group_next(struct m0_sns_cm_iter *it)
Definition: iter.c:474
struct m0_pdclust_src_addr ifc_sa
Definition: iter.h:74
M0_INTERNAL void m0_cob_ns_iter_fini(struct m0_cob_fid_ns_iter *iter)
Definition: ns_iter.c:123
static bool __group_skip(struct m0_sns_cm_iter *it, uint64_t group)
Definition: iter.c:378
uint64_t sf_max_group
Definition: file.h:67
struct m0_layout * sf_layout
Definition: file.h:74
uint64_t ta_obj
Definition: pdclust.h:256
M0_INTERNAL void m0_sns_cm_fctx_unlock(struct m0_sns_cm_file_ctx *fctx)
Definition: file.c:58
struct m0_fom p_fom
Definition: pump.h:51
static struct m0_sns_cm * scm
Definition: cm.c:64
static struct m0_be_emap_cursor it
Definition: extmap.c:46
Definition: iter.c:66
#define M0_BITS(...)
Definition: misc.h:236
M0_INTERNAL int m0_sns_cm_file_lock(struct m0_sns_cm *scm, const struct m0_fid *fid, struct m0_sns_cm_file_ctx **out)
Definition: file.c:404
M0_INTERNAL uint64_t m0_sns_cm_ag_nr_parity_units(const struct m0_pdclust_layout *pl)
Definition: cm_utils.c:228
m0_cm_op
Definition: cm.h:37
struct m0_fid sf_fid
Definition: file.h:63
struct m0_sns_cm_buf_pool sc_ibp
Definition: cm.h:227
#define container_of(ptr, type, member)
Definition: misc.h:33
#define M0_SET0(obj)
Definition: misc.h:64
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
struct m0_poolmach * sf_pm
Definition: file.h:70
M0_INTERNAL void m0_sns_cm_file_attr_and_layout_wait(struct m0_sns_cm_file_ctx *fctx, struct m0_fom *fom)
Definition: file.c:744
M0_INTERNAL bool m0_cm_ag_id_is_set(const struct m0_cm_ag_id *id)
Definition: ag.c:95
M0_INTERNAL bool m0_fid_is_set(const struct m0_fid *fid)
Definition: fid.c:106
M0_INTERNAL int m0_sns_cm_iter_init(struct m0_sns_cm_iter *it)
Definition: iter.c:871
const char * bt_name
Definition: bob.h:73
M0_INTERNAL int iter_idle(struct m0_sns_cm_iter *it)
Definition: iter.c:739
struct m0_fid fid
Definition: di.c:46
return M0_RC(rc)
static struct m0_cm * cm
Definition: cm.c:63
op
Definition: libdemo.c:64
M0_INTERNAL uint64_t agid2group(const struct m0_cm_ag_id *id)
Definition: ag.c:413
#define M0_ENTRY(...)
Definition: trace.h:170
enum m0_cm_op sc_op
Definition: cm.h:209
M0_INTERNAL void m0_cm_ag_cp_add(struct m0_cm_aggr_group *ag, struct m0_cm_cp *cp)
Definition: ag.c:510
static bool unit_has_data(struct m0_sns_cm *scm, uint32_t unit)
Definition: iter.c:588
#define M0_AG_F
Definition: ag.h:54
static struct m0_sns_cm_ag * sag
Definition: cm.c:66
uint32_t ifc_dpupg
Definition: iter.h:64
int i
Definition: dir.c:1033
struct m0_cm_cp sc_base
Definition: cp.h:39
struct m0_mutex sc_file_ctx_mutex
Definition: cm.h:271
static int iter_group_next(struct m0_sns_cm_iter *it)
Definition: iter.c:554
M0_INTERNAL const struct m0_fid M0_MDSERVICE_SLASH_FID
Definition: md_fid.c:63
static enum cm_data_iter_phase iter_phase(const struct m0_sns_cm_iter *it)
Definition: iter.c:127
M0_INTERNAL int m0_sns_cm_file_lock_wait(struct m0_sns_cm_file_ctx *fctx, struct m0_fom *fom)
Definition: file.c:370
M0_INTERNAL int m0_cm_ag_id_cmp(const struct m0_cm_ag_id *id0, const struct m0_cm_ag_id *id1)
Definition: ag.c:73
M0_INTERNAL void m0_sns_cm_file_unlock(struct m0_sns_cm *scm, struct m0_fid *fid)
Definition: file.c:504
#define M0_ASSERT(cond)
const char * scf_name
Definition: sm.h:352
static int iter_fid_next(struct m0_sns_cm_iter *it)
Definition: iter.c:329
bool ifc_cob_is_spare_unit
Definition: iter.h:85
void m0_sm_state_set(struct m0_sm *mach, int state)
Definition: sm.c:478
M0_INTERNAL int __fid_next(struct m0_sns_cm_iter *it, struct m0_fid *fid_next)
Definition: iter.c:188
M0_INTERNAL void m0_cm_ag_put(struct m0_cm_aggr_group *ag)
Definition: ag.c:495
uint64_t ta_frame
Definition: pdclust.h:254
M0_INTERNAL uint64_t m0_sns_cm_ag_nr_local_units(struct m0_sns_cm *scm, struct m0_sns_cm_file_ctx *fctx, uint64_t group)
Definition: cm_utils.c:176
m0_sns_cm_local_unit_type
Definition: cm.h:128
struct m0_fid ifc_gfid
Definition: iter.h:51
Definition: iter.c:74
M0_INTERNAL int m0_cob_ns_iter_init(struct m0_cob_fid_ns_iter *iter, struct m0_fid *gfid, struct m0_cob_domain *cdom)
Definition: ns_iter.c:40
static struct m0_fid cob_fid
Definition: net.c:116
static struct m0_sm_state_descr cm_iter_sd[ITPH_NR]
Definition: iter.c:805
M0_INTERNAL int m0_sns_cm_cp_setup(struct m0_sns_cm_cp *scp, const struct m0_fid *cob_fid, uint64_t stob_offset, uint64_t data_seg_nr, uint64_t failed_unit_index, uint64_t ag_cp_idx)
Definition: cp.c:368
M0_INTERNAL struct m0_cm_aggr_group * m0_cm_aggr_group_locate(struct m0_cm *cm, const struct m0_cm_ag_id *id, bool has_incoming)
Definition: ag.c:262
M0_INTERNAL struct m0_pdclust_layout * m0_layout_to_pdl(const struct m0_layout *l)
Definition: pdclust.c:382
uint64_t u_hi
Definition: types.h:36
static int iter_fid_lock_wait(struct m0_sns_cm_iter *it)
Definition: iter.c:303
M0_INTERNAL bool m0_sns_cm_is_cob_repaired(struct m0_poolmach *pm, uint32_t cob_index)
Definition: cm_utils.c:246
uint64_t f_container
Definition: fid.h:39
static void unit_to_cobfid(struct m0_sns_cm_iter_file_ctx *ifc, struct m0_fid *cob_fid_out)
Definition: iter.c:173
Definition: reqh.h:94
M0_INTERNAL int m0_sns_repair_data_map(struct m0_poolmach *pm, struct m0_pdclust_layout *pl, struct m0_pdclust_instance *pi, uint64_t group_number, uint64_t spare_unit_number, uint64_t *data_unit_id_out)
static void group(void)
Definition: sm.c:386
struct m0_cm_aggr_group * c_ag
Definition: cp.h:172
M0_INTERNAL void m0_sns_cm_fctx_lock(struct m0_sns_cm_file_ctx *fctx)
Definition: file.c:53
M0_INTERNAL struct m0_sns_cm_cp * cp2snscp(const struct m0_cm_cp *cp)
Definition: cp.c:57
static int iter_cob_next(struct m0_sns_cm_iter *it)
Definition: iter.c:690
struct m0_cob_domain * sc_cob_dom
Definition: cm.h:217
#define FID_P(f)
Definition: fid.h:77
#define PRId64
Definition: types.h:57
struct m0_cm_ag_id cm_last_processed_out
Definition: cm.h:224
M0_INTERNAL struct m0_reqh * m0_sns_cm2reqh(const struct m0_sns_cm *snscm)
Definition: cm_utils.c:547
M0_INTERNAL int m0_sns_cm_iter_next(struct m0_cm *cm, struct m0_cm_cp *cp)
Definition: iter.c:762
M0_INTERNAL enum m0_sns_cm_local_unit_type m0_sns_cm_local_unit_type_get(struct m0_sns_cm_file_ctx *fctx, uint64_t group, uint64_t unit)
Definition: cm_utils.c:634
struct m0_sm_group cm_sm_group
Definition: cm.h:185
M0_INTERNAL void m0_sns_cm_buf_wait(struct m0_sns_cm_buf_pool *sbp, struct m0_fom *fom)
Definition: cm.c:803
M0_INTERNAL bool m0_fid_eq(const struct m0_fid *fid0, const struct m0_fid *fid1)
Definition: fid.c:164
uint64_t sa_unit
Definition: pdclust.h:243
uint32_t sd_flags
Definition: sm.h:378
struct m0_sns_cm_iter_file_ctx si_fc
Definition: iter.h:101
uint64_t ifc_group_last
Definition: iter.h:67
struct m0_reqh reqh
Definition: rm_foms.c:48
#define M0_MAGIX_OFFSET(type, field)
Definition: misc.h:356
static int __file_context_init(struct m0_sns_cm_iter *it)
Definition: iter.c:208
struct m0_fid cnr_pver
Definition: cob.h:438
cm_data_iter_phase
Definition: iter.c:65
#define M0_CNT_INC(cnt)
Definition: arith.h:226
#define M0_FI_ENABLED(tag)
Definition: finject.h:231
Definition: fid.h:38
M0_INTERNAL uint64_t m0_sns_cm_data_seg_nr(struct m0_sns_cm *scm, struct m0_pdclust_layout *pl)
Definition: cm.c:845
uint64_t f_key
Definition: fid.h:40
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
M0_INTERNAL uint64_t m0_sns_cm_ag_size(const struct m0_pdclust_layout *pl)
Definition: cm_utils.c:239
static int iter_fid_lock(struct m0_sns_cm_iter *it)
Definition: iter.c:280
static struct m0_sns_cm_cp scp
Definition: cm.c:65
bool sc_is_local
Definition: cp.h:53
Definition: cm.h:166
M0_INTERNAL enum m0_pdclust_unit_type m0_pdclust_unit_classify(const struct m0_pdclust_layout *pl, int unit)
Definition: pdclust.c:425
M0_INTERNAL int m0_sns_cm_file_attr_and_layout(struct m0_sns_cm_file_ctx *fctx)
Definition: file.c:694
struct m0_pools_common * rh_pools
Definition: reqh.h:118
M0_INTERNAL bool m0_sns_cm_unit_is_spare(struct m0_sns_cm_file_ctx *fctx, uint64_t group_nr, uint64_t spare_nr)
Definition: cm_utils.c:277
static int group__next(struct m0_sns_cm_iter *it)
Definition: iter.c:242
M0_INTERNAL void m0_sns_cm_cancel_reservation(struct m0_sns_cm *scm, size_t nr_bufs)
Definition: cm.c:926
struct m0_uint128 ai_hi
Definition: ag.h:50
struct m0_uint128 ai_lo
Definition: ag.h:51
M0_INTERNAL int m0_sns_cm_iter_start(struct m0_sns_cm_iter *it)
Definition: iter.c:888
uint32_t sag_cp_created_nr
Definition: ag.h:60
struct m0_cm_cp_pump cm_cp_pump
Definition: cm.h:257
struct m0_cm sc_base
Definition: cm.h:206
static bool iter_layout_invariant(enum cm_data_iter_phase phase, const struct m0_sns_cm_iter_file_ctx *ifc)
Definition: iter.c:141
struct m0_pdclust_instance * sf_pi
Definition: file.h:77
static struct m0_sns_cm_file_ctx fctx
Definition: net.c:55
M0_INTERNAL int m0_cm_aggr_group_alloc(struct m0_cm *cm, const struct m0_cm_ag_id *id, bool has_incoming, struct m0_cm_aggr_group **out)
Definition: ag.c:330
uint32_t ifc_upg
Definition: iter.h:61
struct m0_sns_cm_iter sc_it
Definition: cm.h:220
struct m0_pdclust_tgt_addr ifc_ta
Definition: iter.h:80
M0_INTERNAL void m0_layout_put(struct m0_layout *l)
Definition: layout.c:893
#define out(...)
Definition: gen.c:41
struct m0_fid gfid
Definition: dir.c:626
Definition: iter.c:116
static void iter_phase_set(struct m0_sns_cm_iter *it, int phase)
Definition: iter.c:135
static int iter_cp_setup(struct m0_sns_cm_iter *it)
Definition: iter.c:612
uint64_t u_lo
Definition: types.h:37
static const struct m0_sm_conf cm_iter_sm_conf
Definition: iter.c:865
int(* sch_ag_setup)(struct m0_sns_cm_ag *sag, struct m0_pdclust_layout *pl)
Definition: cm.h:180
static bool iter_invariant(const struct m0_sns_cm_iter *it)
Definition: iter.c:159
static int __group_alloc(struct m0_sns_cm *scm, struct m0_fid *gfid, uint64_t group, struct m0_pdclust_layout *pl, bool has_incoming, struct m0_cm_aggr_group **ag)
Definition: iter.c:405
M0_BOB_DEFINE(static, &iter_bob, m0_sns_cm_iter)
bool(* sch_is_cob_failed)(struct m0_poolmach *pm, uint32_t cob_index)
Definition: cm.h:188
M0_INTERNAL struct m0_sns_cm_ag * ag2snsag(const struct m0_cm_aggr_group *ag)
Definition: ag.c:391
const struct m0_sns_cm_helpers * sc_helpers
Definition: cm.h:215
int32_t rc
Definition: trigger_fop.h:47
static int(* iter_action[])(struct m0_sns_cm_iter *it)
Definition: iter.c:746
bool cm_abort
Definition: cm.h:282
#define ARRAY_SIZE(a)
Definition: misc.h:45
Definition: ag.h:49
M0_INTERNAL uint32_t m0_pdclust_P(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:367
M0_INTERNAL uint64_t m0_pdclust_unit_size(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:377
M0_INTERNAL const struct m0_fid M0_COB_ROOT_FID
Definition: md_fid.c:39
M0_INTERNAL void m0_sns_cm_iter_fini(struct m0_sns_cm_iter *it)
Definition: iter.c:922
#define FID_F
Definition: fid.h:75
struct m0_cm_ag_id cm_sw_last_updated_hi
Definition: cm.h:220
#define M0_IMPOSSIBLE(fmt,...)
M0_INTERNAL void m0_sns_cm_reserve_space(struct m0_sns_cm *scm, size_t nr_bufs)
Definition: cm.c:916
M0_INTERNAL void m0_sm_fini(struct m0_sm *mach)
Definition: sm.c:331
static uint nr_bufs