Motr  M0
xform.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2013-2021 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_SNSCM
24 #include "lib/trace.h"
25 #include "lib/memory.h"
26 
27 #include "reqh/reqh.h"
28 
29 #include "sns/cm/repair/ag.h"
30 #include "sns/cm/cp.h"
31 #include "sns/cm/cm_utils.h"
32 #include "sns/parity_math.h"
33 #include "sns/cm/file.h"
34 
40 M0_INTERNAL struct m0_sns_cm_repair_ag *
41 sag2repairag(const struct m0_sns_cm_ag *sag);
42 
47 M0_INTERNAL int repair_cp_bufvec_split(struct m0_cm_cp *cp)
48 {
49  struct m0_sns_cm_ag *sag = ag2snsag(cp->c_ag);
50  struct m0_sns_cm_repair_ag *rag;
51 
52  rag = sag2repairag(sag);
53  if (cp->c_buf_nr == 1 ||
55  return 0;
56 
57  return m0_cm_cp_bufvec_split(cp);
58 }
59 
69 static void bufvec_xor(struct m0_bufvec *dst, struct m0_bufvec *src,
70  m0_bcount_t num_bytes)
71 {
72  struct m0_bufvec_cursor s_cur;
73  struct m0_bufvec_cursor d_cur;
74  m0_bcount_t frag_size = 0;
75  struct m0_buf src_buf;
76  struct m0_buf dst_buf;
77 
78  M0_PRE(dst != NULL);
79  M0_PRE(src != NULL);
80 
81  m0_bufvec_cursor_init(&s_cur, src);
82  m0_bufvec_cursor_init(&d_cur, dst);
83  /*
84  * bitwise OR used below to ensure both cursors get moved
85  * without short-circuit logic, also why cursor move is before
86  * simpler num_bytes check.
87  */
88  while (!(m0_bufvec_cursor_move(&d_cur, frag_size) |
89  m0_bufvec_cursor_move(&s_cur, frag_size)) &&
90  num_bytes > 0) {
91  frag_size = min3(m0_bufvec_cursor_step(&d_cur),
92  m0_bufvec_cursor_step(&s_cur),
93  num_bytes);
94  m0_buf_init(&src_buf, m0_bufvec_cursor_addr(&s_cur), frag_size);
95  m0_buf_init(&dst_buf, m0_bufvec_cursor_addr(&d_cur), frag_size);
96  m0_parity_math_buffer_xor(&dst_buf, &src_buf);
97  num_bytes -= frag_size;
98  }
99 }
100 
101 static void cp_xor_recover(struct m0_cm_cp *dst_cp, struct m0_cm_cp *src_cp)
102 {
103  struct m0_net_buffer *src_nbuf;
104  struct m0_net_buffer *dst_nbuf;
105  struct m0_net_buffer_pool *nbp;
106  uint64_t buf_size = 0;
107  uint64_t total_data_seg_nr;
108 
109  M0_PRE(!cp_data_buf_tlist_is_empty(&src_cp->c_buffers));
110  M0_PRE(!cp_data_buf_tlist_is_empty(&dst_cp->c_buffers));
111  M0_PRE(src_cp->c_buf_nr == dst_cp->c_buf_nr);
112 
113  total_data_seg_nr = src_cp->c_data_seg_nr;
114  for (src_nbuf = cp_data_buf_tlist_head(&src_cp->c_buffers),
115  dst_nbuf = cp_data_buf_tlist_head(&dst_cp->c_buffers);
116  src_nbuf != NULL && dst_nbuf != NULL;
117  src_nbuf = cp_data_buf_tlist_next(&src_cp->c_buffers, src_nbuf),
118  dst_nbuf = cp_data_buf_tlist_next(&dst_cp->c_buffers, dst_nbuf))
119  {
120  nbp = src_nbuf->nb_pool;
121  if (total_data_seg_nr < nbp->nbp_seg_nr)
122  buf_size = total_data_seg_nr * nbp->nbp_seg_size;
123  else {
124  total_data_seg_nr -= nbp->nbp_seg_nr;
126  }
127  bufvec_xor(&dst_nbuf->nb_buffer, &src_nbuf->nb_buffer,
128  buf_size);
129  }
130 }
131 
132 static int cp_rs_recover(struct m0_cm_cp *src_cp, uint32_t failed_index)
133 {
134  struct m0_sns_cm_cp *scp;
135  struct m0_net_buffer *nbuf_head;
136  struct m0_sns_cm_repair_ag *rag = sag2repairag(ag2snsag(src_cp->c_ag));
138  int ret;
139 
140  nbuf_head = cp_data_buf_tlist_head(&src_cp->c_buffers);
141  scp = cp2snscp(src_cp);
143  ret = m0_sns_ir_recover(&rag->rag_ir, &nbuf_head->nb_buffer,
144  &src_cp->c_xform_cp_indices, failed_index, bt);
145  return M0_RC(ret);
146 }
147 
149 static void res_cp_bitmap_merge(struct m0_cm_cp *dst, struct m0_cm_cp *src)
150 {
151  int i;
152 
153  M0_PRE(dst->c_xform_cp_indices.b_nr <= src->c_xform_cp_indices.b_nr);
154 
155  for (i = 0; i < src->c_xform_cp_indices.b_nr; ++i) {
156  if (m0_bitmap_get(&src->c_xform_cp_indices, i))
157  m0_bitmap_set(&dst->c_xform_cp_indices, i, true);
158  }
159 }
160 
161 static int res_cp_enqueue(struct m0_cm_cp *cp)
162 {
163  int rc;
164 
166  if (rc != 0)
167  return M0_ERR(rc);
168 
169  return M0_RC(m0_cm_cp_enqueue(cp->c_ag->cag_cm, cp));
170 }
171 
174 {
175  struct m0_sns_cm_ag *sag = &rag->rag_base;
176  struct m0_cm_aggr_group *ag = &sag->sag_base;
177  struct m0_cm_cp *acc = &fc->fc_tgt_acc_cp.sc_base;
178  uint64_t incoming_nr;
179  int rc = 0;
180  int is_local_cob;
181  struct m0_pool_version *pver;
182 
183  /*
184  * Check if all copy packets are processed at this stage,
185  * For incoming path transformation can be marked as complete
186  * iff all the local (@ag->cag_cp_local_nr) as well as all the
187  * incoming (@rag->rag_base.sag_incoming_nr) copy packets are
188  * transformed for the given aggregation group.
189  * For outgoing path, iff all "local" copy packets in
190  * aggregation group are transformed, then transformation can
191  * be marked complete.
192  */
193  incoming_nr = sag->sag_incoming_units_nr + ag->cag_cp_local_nr;
195  is_local_cob = m0_sns_cm_is_local_cob(ag->cag_cm, pver,
196  &fc->fc_tgt_cobfid);
197  if ((is_local_cob &&
198  m0_sns_cm_ag_acc_is_full_with(acc, incoming_nr)) ||
199  (!is_local_cob &&
201  fc->fc_is_active = true;
202  rc = res_cp_enqueue(acc);
203  if (rc != 0)
204  fc->fc_is_active = false;
205  }
206  return M0_RC(rc);
207 }
208 
222 M0_INTERNAL int m0_sns_cm_repair_cp_xform(struct m0_cm_cp *cp)
223 {
224  struct m0_sns_cm_ag *sns_ag;
225  struct m0_sns_cm_cp *scp;
226  struct m0_sns_cm_repair_ag *rag;
227  struct m0_cm_aggr_group *ag;
228  struct m0_cm_cp *res_cp;
229  struct m0_sns_cm_file_ctx *fctx;
230  struct m0_pdclust_layout *pl;
231  struct m0_cm_ag_id id;
232  enum m0_parity_cal_algo pm_algo;
233  int rc = 0;
234  int i;
235 
236  M0_PRE(cp != NULL && m0_fom_phase(&cp->c_fom) == M0_CCP_XFORM);
237 
238  ag = cp->c_ag;
239  id = ag->cag_id;
240  scp = cp2snscp(cp);
241  sns_ag = ag2snsag(ag);
242  rag = sag2repairag(sns_ag);
243  pm_algo = rag->rag_math.pmi_parity_algo;
244  fctx = sns_ag->sag_fctx;
246  M0_ASSERT_INFO(ergo(!m0_pdclust_is_replicated(pl), M0_IN(pm_algo,
249  "parity_algo=%d", (int)pm_algo);
250 
251  m0_cm_ag_lock(ag);
252  M0_LOG(M0_DEBUG, "xform: id=["M0_AG_F"] local_cp_nr=[%" PRId64 "]"
253  " transformed_cp_nr=[%" PRId64 "] global_cp_nr=[%" PRId64 "] "
254  "has_incoming=%d c_ag_cp_idx=[%" PRId64 "]",
255  M0_AG_P(&id), ag->cag_cp_local_nr,
257  ag->cag_has_incoming, cp->c_ag_cp_idx);
258  /* Increment number of transformed copy packets in the accumulator. */
260  if (!ag->cag_has_incoming)
262  else
263  /*
264  * For every failure in an aggregation group, 1 accumulator copy
265  * packet is created.
266  * So Number of transformed copy packets in an aggregation group
267  * must not exceed the remaining live data/parity copy packets
268  * multiplied by the total number of failures in an aggregation
269  * group.
270  */
272  (ag->cag_cp_global_nr - sns_ag->sag_fnr) *
273  sns_ag->sag_fnr);
274 
275  if (!m0_pdclust_is_replicated(pl) &&
276  pm_algo == M0_PARITY_CAL_ALGO_REED_SOLOMON) {
278  if (rc != 0)
279  goto out;
281  if (rc != 0)
282  goto out;
283  }
284  /*
285  * Local copy packets are merged with all the accumulators while the
286  * non-local or incoming copy packets are merged with the accumulators
287  * corresponding to the respective failed indices.
288  */
289  for (i = 0; i < sns_ag->sag_fnr; ++i) {
291  continue;
292  res_cp = &rag->rag_fc[i].fc_tgt_acc_cp.sc_base;
293  /*
294  * N == 1, no need for transformation, just copy data to the
295  * respective accumulator.
296  */
297  if (m0_pdclust_is_replicated(pl)) {
298  if (scp->sc_is_local ||
300  m0_cm_cp_data_copy(cp, res_cp);
301  } else if (pm_algo == M0_PARITY_CAL_ALGO_XOR)
302  cp_xor_recover(res_cp, cp);
303 
304  /*
305  * Merge the bitmaps of incoming copy packet with the
306  * resultant copy packet.
307  */
308  if (cp->c_xform_cp_indices.b_nr > 0) {
309  if (scp->sc_is_local || (scp->sc_failed_idx ==
310  rag->rag_fc[i].fc_failed_idx)) {
311  res_cp_bitmap_merge(res_cp, cp);
313  if (rc != 0 && rc != -ENOENT)
314  goto out;
315  }
316  }
317  }
318 out:
319  if (rc == -ESHUTDOWN) {
321  m0_cm_ag_unlock(ag);
322  return M0_RC(M0_FSO_AGAIN);
323  }
324  /*
325  * Once transformation is complete, transition copy packet fom to
326  * M0_CCP_FINI since it is not needed anymore. This copy packet will
327  * be freed during M0_CCP_FINI phase execution.
328  * Since the buffers of this copy packet are released back to the
329  * buffer pool, merged bufvec is split back to its original form
330  * to be reused by other copy packets.
331  */
332  if (rc == 0 || rc == -ENOENT)
334 
336  rc = M0_FSO_WAIT;
337  m0_cm_ag_unlock(ag);
338 
339  return M0_RC(rc);
340 }
341 
342 #undef M0_TRACE_SUBSYSTEM
343 
344 /*
345  * Local variables:
346  * c-indentation-style: "K&R"
347  * c-basic-offset: 8
348  * tab-width: 8
349  * fill-column: 80
350  * scroll-step: 1
351  * End:
352  */
uint64_t id
Definition: cob.h:2380
M0_INTERNAL void m0_cm_ag_unlock(struct m0_cm_aggr_group *ag)
Definition: ag.c:63
#define M0_PRE(cond)
M0_INTERNAL bool m0_pdclust_is_replicated(struct m0_pdclust_layout *play)
Definition: pdclust.c:829
struct m0_net_buffer_pool * nb_pool
Definition: net.h:1508
struct m0_parity_math rag_math
Definition: ag.h:96
#define NULL
Definition: misc.h:38
#define M0_AG_P(ag)
Definition: ag.h:55
static struct m0_bufvec dst
Definition: xform.c:61
struct m0_bitmap c_xform_cp_indices
Definition: cp.h:181
enum m0_parity_cal_algo pmi_parity_algo
Definition: parity_math.h:125
struct m0_bufvec nb_buffer
Definition: net.h:1322
static int res_cp_enqueue(struct m0_cm_cp *cp)
Definition: xform.c:161
#define ergo(a, b)
Definition: misc.h:293
m0_bcount_t nbp_seg_size
Definition: buffer_pool.h:255
static int cp_rs_recover(struct m0_cm_cp *src_cp, uint32_t failed_index)
Definition: xform.c:132
#define M0_LOG(level,...)
Definition: trace.h:167
Definition: cp.h:160
M0_INTERNAL void m0_parity_math_buffer_xor(struct m0_buf *dest, const struct m0_buf *src)
Definition: parity_math.c:415
M0_INTERNAL bool m0_sns_cm_is_local_cob(const struct m0_cm *cm, const struct m0_pool_version *pv, const struct m0_fid *cob_fid)
Definition: cm_utils.c:449
M0_INTERNAL void m0_buf_init(struct m0_buf *buf, void *data, uint32_t nob)
Definition: buf.c:37
struct m0_layout * sf_layout
Definition: file.h:74
struct m0_cm_ag_id cag_id
Definition: ag.h:72
M0_INTERNAL int m0_cm_cp_bufvec_split(struct m0_cm_cp *cp)
Definition: cp.c:768
M0_INTERNAL void * m0_bufvec_cursor_addr(struct m0_bufvec_cursor *cur)
Definition: vec.c:597
uint64_t m0_bcount_t
Definition: types.h:77
m0_parity_cal_algo
Definition: parity_math.h:49
uint64_t c_ag_cp_idx
Definition: cp.h:175
m0_fom_phase
Definition: fom.h:372
uint32_t sag_fnr
Definition: ag.h:51
uint64_t cag_cp_global_nr
Definition: ag.h:86
return M0_RC(rc)
Definition: buf.h:37
static struct btype bt[]
Definition: beck.c:459
#define M0_AG_F
Definition: ag.h:54
M0_INTERNAL bool m0_bufvec_cursor_move(struct m0_bufvec_cursor *cur, m0_bcount_t count)
Definition: vec.c:574
M0_INTERNAL void m0_cm_cp_data_copy(struct m0_cm_cp *src, struct m0_cm_cp *dst)
Definition: cp.c:828
static struct m0_sns_cm_ag * sag
Definition: cm.c:66
int i
Definition: dir.c:1033
struct m0_cm_cp sc_base
Definition: cp.h:39
static void res_cp_bitmap_merge(struct m0_cm_cp *dst, struct m0_cm_cp *src)
Definition: xform.c:149
return M0_ERR(-EOPNOTSUPP)
struct m0_sns_cm_ag rag_base
Definition: ag.h:77
M0_INTERNAL void m0_cm_ag_lock(struct m0_cm_aggr_group *ag)
Definition: ag.c:58
struct m0_sns_ir rag_ir
Definition: ag.h:99
M0_INTERNAL m0_bcount_t m0_bufvec_cursor_step(const struct m0_bufvec_cursor *cur)
Definition: vec.c:581
#define M0_ASSERT(cond)
M0_INTERNAL struct m0_pool_version * m0_sns_cm_pool_version_get(struct m0_sns_cm_file_ctx *fctx)
Definition: file.c:686
static struct m0_net_buffer_pool nbp
Definition: xform.c:57
struct m0_fid pver
Definition: idx_dix.c:74
struct m0_fid fc_tgt_cobfid
Definition: ag.h:60
uint32_t c_data_seg_nr
Definition: cp.h:190
void m0_fom_phase_move(struct m0_fom *fom, int32_t rc, int phase)
Definition: fom.c:1699
M0_INTERNAL int m0_sns_ir_recover(struct m0_sns_ir *ir, struct m0_bufvec *bufvec, const struct m0_bitmap *bitmap, uint32_t failed_index, enum m0_sns_ir_block_type block_type)
Definition: parity_math.c:503
struct m0_cm * cag_cm
Definition: ag.h:70
M0_INTERNAL void m0_bufvec_cursor_init(struct m0_bufvec_cursor *cur, const struct m0_bufvec *bvec)
Definition: vec.c:563
M0_INTERNAL struct m0_pdclust_layout * m0_layout_to_pdl(const struct m0_layout *l)
Definition: pdclust.c:382
struct m0_sns_cm_cp fc_tgt_acc_cp
Definition: ag.h:45
M0_INTERNAL void m0_bitmap_set(struct m0_bitmap *map, size_t idx, bool val)
Definition: bitmap.c:139
M0_INTERNAL struct m0_sns_cm_repair_ag * sag2repairag(const struct m0_sns_cm_ag *sag)
Definition: ag.c:61
struct m0_cm_aggr_group * c_ag
Definition: cp.h:172
uint64_t sc_failed_idx
Definition: cp.h:55
static void bufvec_xor(struct m0_bufvec *dst, struct m0_bufvec *src, m0_bcount_t num_bytes)
Definition: xform.c:69
M0_INTERNAL struct m0_sns_cm_cp * cp2snscp(const struct m0_cm_cp *cp)
Definition: cp.c:57
M0_INTERNAL int m0_cm_cp_bufvec_merge(struct m0_cm_cp *cp)
Definition: cp.c:752
#define PRId64
Definition: types.h:57
uint64_t cag_transformed_cp_nr
Definition: ag.h:95
M0_INTERNAL bool m0_sns_cm_ag_acc_is_full_with(const struct m0_cm_cp *acc, uint64_t nr_cps)
Definition: ag.c:562
M0_INTERNAL int repair_cp_bufvec_split(struct m0_cm_cp *cp)
Definition: xform.c:47
struct m0_sns_cm_file_ctx * sag_fctx
Definition: ag.h:48
M0_INTERNAL int m0_cm_cp_enqueue(struct m0_cm *cm, struct m0_cm_cp *cp)
Definition: cp.c:688
struct m0_sns_cm_repair_ag_failure_ctx * rag_fc
Definition: ag.h:93
uint32_t c_buf_nr
Definition: cp.h:187
#define M0_CNT_INC(cnt)
Definition: arith.h:226
static void cp_xor_recover(struct m0_cm_cp *dst_cp, struct m0_cm_cp *src_cp)
Definition: xform.c:101
static struct m0_sns_cm_cp scp
Definition: cm.c:65
static int repair_ag_fc_acc_post(struct m0_sns_cm_repair_ag *rag, struct m0_sns_cm_repair_ag_failure_ctx *fc)
Definition: xform.c:172
bool sc_is_local
Definition: cp.h:53
M0_INTERNAL bool m0_bitmap_get(const struct m0_bitmap *map, size_t idx)
Definition: bitmap.c:105
uint64_t cag_cp_local_nr
Definition: ag.h:92
uint32_t sag_incoming_units_nr
Definition: ag.h:66
struct m0_tl c_buffers
Definition: cp.h:184
#define M0_ASSERT_INFO(cond, fmt,...)
m0_sns_ir_block_type
Definition: parity_math.h:60
static struct m0_sns_cm_file_ctx fctx
Definition: net.c:55
static struct m0_sns_cm_repair_ag rag
Definition: net.c:54
static uint32_t buf_size
Definition: ad.c:75
bool cag_has_incoming
Definition: ag.h:101
#define out(...)
Definition: gen.c:41
struct m0_cm_aggr_group sag_base
Definition: ag.h:46
#define min3(a, b, c)
Definition: arith.h:103
size_t b_nr
Definition: bitmap.h:44
struct m0_fom c_fom
Definition: cp.h:161
M0_INTERNAL int m0_sns_cm_repair_cp_xform(struct m0_cm_cp *cp)
Definition: xform.c:222
struct m0_pdclust_src_addr src
Definition: fd.c:108
M0_INTERNAL struct m0_sns_cm_ag * ag2snsag(const struct m0_cm_aggr_group *ag)
Definition: ag.c:391
int32_t rc
Definition: trigger_fop.h:47
Definition: ag.h:49
Definition: vec.h:145