Motr  M0
parity_repair.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2020 Seagate Technology LLC and/or its Affiliates
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * For any questions about this software or licensing,
17  * please email opensource@seagate.com or cortx-questions@seagate.com.
18  *
19  */
20 
21 
22 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_SNSCM
23 #include "lib/trace.h"
24 #include "lib/misc.h"
25 #include "lib/errno.h"
26 #include "sns/parity_repair.h"
27 #include "ioservice/fid_convert.h" /* m0_fid_cob_device_id */
28 
30  uint64_t group_number, uint64_t unit_number,
31  uint32_t *device_index_out)
32 {
33  struct m0_pdclust_src_addr sa;
34  struct m0_pdclust_tgt_addr ta;
35 
36  /* Find out the device index. */
37  M0_SET0(&sa);
38  M0_SET0(&ta);
39 
40  sa.sa_group = group_number;
41  sa.sa_unit = unit_number;
42  m0_fd_fwd_map(pi, &sa, &ta);
43  *device_index_out = ta.ta_obj;
44  M0_LEAVE("index:%d", (int)ta.ta_obj);
45 }
46 
47 static int _spare_next(struct m0_poolmach *pm,
48  const struct m0_fid *fid,
49  struct m0_pdclust_layout *pl,
50  struct m0_pdclust_instance *pi,
51  uint64_t group_number,
52  uint64_t unit_number,
53  uint32_t *spare_slot_out,
54  uint32_t *spare_slot_out_prev,
55  bool break_next)
56 {
57  uint32_t device_index;
58  uint32_t device_index_new;
59  int rc;
60 
61  M0_ENTRY("unit number:%d", (int)unit_number);
62 
63  M0_PRE(pm != NULL && fid != NULL && pl != NULL);
64 
65  device_index_get(pi, group_number, unit_number, &device_index);
66  *spare_slot_out_prev = unit_number;
67 
68  while (1) {
69  rc = m0_poolmach_sns_repair_spare_query(pm, device_index,
70  spare_slot_out);
71  if (rc != 0)
72  return M0_ERR(rc);
73 
74  /*
75  * Find out if spare slot's corresponding device index is
76  * failed. If yes, find out new spare.
77  */
78  device_index_get(pi, group_number,
79  m0_pdclust_N(pl) + m0_pdclust_K(pl) +
80  *spare_slot_out, &device_index_new);
81 
83  device_index_new) && !break_next) {
84  device_index = device_index_new;
85  *spare_slot_out_prev = *spare_slot_out;
86  } else
87  break;
88  }
89  /*
90  * Return the absolute index of spare with respect to the aggregation
91  * group.
92  */
93  if (rc == 0) {
94  *spare_slot_out += m0_pdclust_N(pl) + m0_pdclust_K(pl);
95  if (*spare_slot_out_prev != unit_number)
96  *spare_slot_out_prev += m0_pdclust_N(pl) +
97  m0_pdclust_K(pl);
98  }
99 
100  return M0_RC(rc);
101 }
102 
103 M0_INTERNAL int m0_sns_repair_spare_map(struct m0_poolmach *pm,
104  const struct m0_fid *fid,
105  struct m0_pdclust_layout *pl,
106  struct m0_pdclust_instance *pi,
107  uint64_t group, uint64_t unit,
108  uint32_t *spare_slot_out,
109  uint32_t *spare_slot_out_prev)
110 {
111  return _spare_next(pm, fid, pl, pi, group, unit, spare_slot_out,
112  spare_slot_out_prev, false);
113 }
114 
115 M0_INTERNAL int m0_sns_repair_spare_rebalancing(struct m0_poolmach *pm,
116  const struct m0_fid *fid,
117  struct m0_pdclust_layout *pl,
118  struct m0_pdclust_instance *pi,
119  uint64_t group, uint64_t unit,
120  uint32_t *spare_slot_out,
121  uint32_t *spare_slot_out_prev)
122 {
123  enum m0_pool_nd_state state_out;
124  uint32_t device_index;
125  int rc;
126 
127  do {
128  rc = _spare_next(pm, fid, pl, pi, group, unit, spare_slot_out,
129  spare_slot_out_prev, true);
130  if (rc == 0) {
131  device_index_get(pi, group, *spare_slot_out, &device_index);
132  rc = m0_poolmach_device_state(pm, device_index, &state_out);
133  }
134  unit = *spare_slot_out;
135  } while (rc == 0 && state_out != M0_PNDS_SNS_REBALANCING);
136 
137  return M0_RC(rc);
138 }
139 
140 static bool frame_eq(struct m0_pdclust_instance *pi, uint64_t group_number,
141  uint64_t frame, uint32_t device_index)
142 {
143  struct m0_pdclust_src_addr sa;
144  struct m0_pdclust_tgt_addr ta;
145 
146  M0_PRE(pi != NULL);
147 
148  M0_SET0(&sa);
149  M0_SET0(&ta);
150 
151  ta.ta_frame = frame;
152  ta.ta_obj = device_index;
153 
154  m0_fd_bwd_map(pi, &ta, &sa);
155  return sa.sa_group == group_number;
156 }
157 
158 static uint64_t frame_get(struct m0_pdclust_instance *pi, uint64_t spare_frame,
159  uint64_t group_number, uint32_t device_index)
160 {
161  uint64_t frame;
162  bool frame_found;
163 
164  M0_PRE(pi != NULL);
165 
166  /* We look at spare_frame - 1, spare_frame and spare_frame + 1 to find
167  * appropriate data/parity unit corresponding to spare unit for a
168  * given group number.
169  */
170  if (spare_frame != 0) {
171  frame = spare_frame - 1;
172  frame_found = frame_eq(pi, group_number, frame, device_index);
173  if (frame_found)
174  goto out;
175  }
176 
177  frame = spare_frame;
178  frame_found = frame_eq(pi, group_number, frame, device_index);
179  if (frame_found)
180  goto out;
181 
182  frame = spare_frame + 1;
183  frame_found = frame_eq(pi, group_number, frame, device_index);
184 
185 out:
186  if (frame_found)
187  return frame;
188  else
189  return M0_RC(-ENOENT);
190 }
191 
192 M0_INTERNAL int m0_sns_repair_data_map(struct m0_poolmach *pm,
193  struct m0_pdclust_layout *pl,
194  struct m0_pdclust_instance *pi,
195  uint64_t group_number,
196  uint64_t spare_unit_number,
197  uint64_t *data_unit_id_out)
198 {
199  int rc;
200  struct m0_pdclust_src_addr sa;
201  struct m0_pdclust_tgt_addr ta;
202  enum m0_pool_nd_state state_out;
203  uint64_t spare_in;
204  uint32_t device_index;
205  uint64_t spare_id;
206  uint64_t frame;
207 
208  M0_PRE(pm != NULL && pl != NULL && pi != NULL);
209 
210  spare_in = spare_unit_number;
211 
212  do {
213  spare_id = spare_in - m0_pdclust_N(pl) -
214  m0_pdclust_K(pl);
215  /*
216  * Fetch the correspinding data/parity unit device index for
217  * the given spare unit.
218  */
219  device_index = pm->pm_state->pst_spare_usage_array[spare_id].
221 
222  if (device_index == POOL_PM_SPARE_SLOT_UNUSED) {
223  rc = -ENOENT;
224  goto out;
225  }
226 
227  M0_SET0(&sa);
228  M0_SET0(&ta);
229  sa.sa_group = group_number;
230  sa.sa_unit = spare_in;
231  m0_fd_fwd_map(pi, &sa, &ta);
232  /*
233  * Find the data/parity unit frame for the @group_number on the
234  * given device represented by @device_index.
235  */
236  frame = frame_get(pi, ta.ta_frame, group_number, device_index);
237  if (frame == -ENOENT) {
238  rc = -ENOENT;
239  goto out;
240  }
241 
242  M0_SET0(&sa);
243  M0_SET0(&ta);
244 
245  ta.ta_frame = frame;
246  ta.ta_obj = device_index;
247 
248  rc = m0_poolmach_device_state(pm, device_index, &state_out);
249  if (rc != 0) {
250  rc = -ENOENT;
251  goto out;
252  }
253 
254  /*
255  * Doing inverse mapping from the frame in the device to the
256  * corresponding unit in parity group @group_number.
257  */
258  m0_fd_bwd_map(pi, &ta, &sa);
259 
260  *data_unit_id_out = sa.sa_unit;
261 
262  /*
263  * It is possible that the unit mapped corresponding to the given
264  * spare_unit_number is same as the spare_unit_number.
265  * Thus this means that there is no data/parity unit repaired on
266  * the given spare_unit_number and the spare is empty.
267  */
268  if (spare_unit_number == sa.sa_unit) {
269  rc = -ENOENT;
270  goto out;
271  }
272 
273  /*
274  * We have got another spare unit, so further try again to map
275  * this spare unit to the actual failed data/parity unit.
276  */
277  spare_in = sa.sa_unit;
278 
279  } while(m0_pdclust_unit_classify(pl, sa.sa_unit) == M0_PUT_SPARE &&
280  M0_IN(state_out, (M0_PNDS_SNS_REPAIRED,
282 out:
283  return M0_RC(rc);
284 }
285 
286 #undef M0_TRACE_SUBSYSTEM
287 /*
288  * Local variables:
289  * c-indentation-style: "K&R"
290  * c-basic-offset: 8
291  * tab-width: 8
292  * fill-column: 80
293  * scroll-step: 1
294  * End:
295  */
struct m0_poolmach_state * pm_state
Definition: pool_machine.h:169
#define M0_PRE(cond)
uint64_t sa_group
Definition: pdclust.h:241
#define NULL
Definition: misc.h:38
static void device_index_get(struct m0_pdclust_instance *pi, uint64_t group_number, uint64_t unit_number, uint32_t *device_index_out)
Definition: parity_repair.c:29
Definition: storage.c:103
M0_LEAVE()
M0_INTERNAL int m0_sns_repair_spare_map(struct m0_poolmach *pm, const struct m0_fid *fid, struct m0_pdclust_layout *pl, struct m0_pdclust_instance *pi, uint64_t group, uint64_t unit, uint32_t *spare_slot_out, uint32_t *spare_slot_out_prev)
M0_INTERNAL int m0_sns_repair_spare_rebalancing(struct m0_poolmach *pm, const struct m0_fid *fid, struct m0_pdclust_layout *pl, struct m0_pdclust_instance *pi, uint64_t group, uint64_t unit, uint32_t *spare_slot_out, uint32_t *spare_slot_out_prev)
uint64_t ta_obj
Definition: pdclust.h:256
M0_INTERNAL int m0_poolmach_device_state(struct m0_poolmach *pm, uint32_t device_index, enum m0_pool_nd_state *state_out)
Definition: pool_machine.c:816
#define M0_SET0(obj)
Definition: misc.h:64
struct m0_fid fid
Definition: di.c:46
return M0_RC(rc)
static int _spare_next(struct m0_poolmach *pm, const struct m0_fid *fid, struct m0_pdclust_layout *pl, struct m0_pdclust_instance *pi, uint64_t group_number, uint64_t unit_number, uint32_t *spare_slot_out, uint32_t *spare_slot_out_prev, bool break_next)
Definition: parity_repair.c:47
#define M0_ENTRY(...)
Definition: trace.h:170
return M0_ERR(-EOPNOTSUPP)
M0_INTERNAL uint32_t m0_pdclust_N(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:352
m0_pool_nd_state
Definition: pool_machine.h:57
uint64_t ta_frame
Definition: pdclust.h:254
static bool frame_eq(struct m0_pdclust_instance *pi, uint64_t group_number, uint64_t frame, uint32_t device_index)
struct m0_pdclust_instance pi
Definition: fd.c:107
M0_INTERNAL uint32_t m0_pdclust_K(const struct m0_pdclust_layout *pl)
Definition: pdclust.c:357
M0_INTERNAL bool m0_poolmach_device_is_in_spare_usage_array(struct m0_poolmach *pm, uint32_t device_index)
Definition: pool_machine.c:867
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
M0_INTERNAL void m0_fd_bwd_map(struct m0_pdclust_instance *pi, const struct m0_pdclust_tgt_addr *tgt, struct m0_pdclust_src_addr *src)
Definition: fd.c:959
static uint64_t frame_get(struct m0_pdclust_instance *pi, uint64_t spare_frame, uint64_t group_number, uint32_t device_index)
uint64_t sa_unit
Definition: pdclust.h:243
Definition: fid.h:38
uint32_t psu_device_index
Definition: pool.h:413
M0_INTERNAL int m0_poolmach_sns_repair_spare_query(struct m0_poolmach *pm, uint32_t device_index, uint32_t *spare_slot_out)
Definition: pool_machine.c:875
M0_INTERNAL enum m0_pdclust_unit_type m0_pdclust_unit_classify(const struct m0_pdclust_layout *pl, int unit)
Definition: pdclust.c:425
#define out(...)
Definition: gen.c:41
M0_INTERNAL void m0_fd_fwd_map(struct m0_pdclust_instance *pi, const struct m0_pdclust_src_addr *src, struct m0_pdclust_tgt_addr *tgt)
Definition: fd.c:838
int32_t rc
Definition: trigger_fop.h:47
struct m0_pool_spare_usage * pst_spare_usage_array
Definition: pool_machine.h:137