Motr  M0
failvec.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_HA
24 #include "lib/trace.h" /* M0_ERR_INFO */
25 #include "lib/chan.h"
26 #include "lib/memory.h" /* M0_ALLOC_PTR */
27 #include "lib/errno.h" /* ENOMEM */
28 #include "lib/finject.h" /* M0_FI_ENABLED */
29 #include "module/instance.h" /* m0_get */
30 #include "ha/failvec.h"
31 #include "ha/msg.h" /* struct m0_ha_msg */
32 #include "ha/link.h" /* m0_ha_link */
33 #include "ha/note.h" /* m0_ha_note_handler_msg */
34 #include "pool/pool_machine.h" /* m0_poolmach_failvec_apply */
35 #include "pool/pool.h"
36 #include "reqh/reqh.h"
37 #include "fid/fid.h"
38 
40  struct m0_chan *fhr_chan;
42  /* unique identifier for the pool. */
43  struct m0_fid fhr_fid;
44  /* Pool-machine to be updated on failvec. */
46  /* Generation count for cookie. */
47  uint64_t fhr_gen;
48  uint64_t fhr_magic;
49 };
50 
51 static uint32_t fvec_rep_msg_vec_len(const struct m0_ha_msg *msg)
52 {
53  return msg->hm_data.u.hed_fvec_rep.mfp_nr;
54 }
55 
56 static const struct m0_cookie*
57  fvec_msg_cookie_get(const struct m0_ha_msg *msg)
58 {
60  &msg->hm_data.u.hed_fvec_req.mfq_cookie :
61  &msg->hm_data.u.hed_fvec_rep.mfp_cookie;
62 }
63 static const struct m0_ha_note * fvec_rep_msg_to_note(const struct m0_ha_msg
64  *msg)
65 {
66  return msg->hm_data.u.hed_fvec_rep.mfp_vec.hmna_arr;
67 }
68 static const struct m0_fid*
69  fvec_msg_to_pool(const struct m0_ha_msg *msg)
70 {
71  return &msg->hm_data.u.hed_fvec_req.mfq_pool;
72 }
73 
74 static uint32_t fvec_msg_type(const struct m0_ha_msg *msg)
75 {
76  return msg->hm_data.hed_type;
77 }
78 M0_TL_DESCR_DEFINE(ha_fvreq, "failure-vec-req", static,
79  struct ha_fvec_handler_request, fhr_tlink, fhr_magic,
80  20, 21); /* XXX */
81 M0_TL_DEFINE(ha_fvreq, static, struct ha_fvec_handler_request);
82 
83 static void ha_fvec_handler_msg(struct m0_ha_handler *hh,
84  struct m0_ha *ha,
85  struct m0_ha_link *hl,
86  struct m0_ha_msg *msg,
87  uint64_t tag,
88  void *data)
89 {
90  struct m0_ha_fvec_handler *hfh;
91 
92  hfh = container_of(hh, struct m0_ha_fvec_handler, hfh_handler);
93  M0_ASSERT(hfh == data);
94 
95  switch (fvec_msg_type(msg)) {
97  m0_ha_fvec_req_handler(hfh, msg, hl);
98  break;
100  m0_ha_fvec_rep_handler(hfh, msg);
101  break;
102  default:
103  M0_LOG(M0_DEBUG, "fvec handler being evoked for non-fvec msg");
104  break;
105  }
106 }
107 
108 M0_INTERNAL int m0_ha_fvec_handler_init(struct m0_ha_fvec_handler *hfh,
109  struct m0_ha_dispatcher *hd)
110 {
111  M0_PRE(M0_IS0(hfh));
112 
113  m0_mutex_init(&hfh->hfh_lock);
114  ha_fvreq_tlist_init(&hfh->hfh_fvreq);
115  hfh->hfh_dispatcher = hd;
116  hfh->hfh_handler = (struct m0_ha_handler) {
117  .hh_data = hfh,
118  .hh_msg_received_cb = &ha_fvec_handler_msg,
119  };
121  M0_ASSERT(m0_get()->i_fvec_handler == NULL);
122  m0_get()->i_fvec_handler = hfh;
123  return 0;
124 }
125 
126 M0_INTERNAL void m0_ha_fvec_handler_fini(struct m0_ha_fvec_handler *hfh)
127 {
128  M0_ASSERT(m0_get()->i_fvec_handler == hfh);
131  ha_fvreq_tlist_fini(&hfh->hfh_fvreq);
132  m0_mutex_fini(&hfh->hfh_lock);
133 }
134 
135 M0_INTERNAL int m0_ha_fvec_handler_add(struct m0_ha_fvec_handler *hfh,
136  const struct m0_fid *pool_fid,
137  struct m0_poolmach *pool_mach,
138  struct m0_chan *chan,
139  struct m0_cookie *cookie)
140 {
141  struct ha_fvec_handler_request *fvec_req;
142 
143  M0_ENTRY("pool_fid"FID_F"PVER fid"FID_F, FID_P(pool_fid),
144  FID_P(&pool_mach->pm_pver->pv_id));
145 
146  M0_PRE(hfh != NULL);
147 
148  M0_ALLOC_PTR(fvec_req);
149  if (fvec_req == NULL)
150  return M0_ERR_INFO(-ENOMEM, "No sufficient memory to"
151  "create a failvec fetch request");
152  m0_mutex_lock(&hfh->hfh_lock);
153  *fvec_req = (struct ha_fvec_handler_request) {
154  .fhr_chan = chan,
155  .fhr_fid = *pool_fid,
156  .fhr_pmach = pool_mach,
157  };
158  m0_cookie_new(&fvec_req->fhr_gen);
159  m0_cookie_init(cookie, &fvec_req->fhr_gen);
160  ha_fvreq_tlink_init_at_tail(fvec_req, &hfh->hfh_fvreq);
161  m0_mutex_unlock(&hfh->hfh_lock);
162  return M0_RC(0);
163 }
164 
165 M0_INTERNAL void m0_ha_fvec_rep_handler(struct m0_ha_fvec_handler *hfh,
166  const struct m0_ha_msg *msg)
167 {
168  struct ha_fvec_handler_request *fhr;
169  struct m0_cookie cookie;
170  struct m0_ha_nvec nvec;
171 
173  m0_mutex_lock(&hfh->hfh_lock);
174  cookie = *(fvec_msg_cookie_get(msg));
175  fhr = m0_cookie_of(&cookie, struct ha_fvec_handler_request,
176  fhr_gen);
177  M0_ASSERT(fhr != NULL);
178  ha_fvreq_tlink_del_fini(fhr);
179  m0_mutex_unlock(&hfh->hfh_lock);
180  nvec.nv_nr = fvec_rep_msg_vec_len(msg);
181  nvec.nv_note = (struct m0_ha_note *)fvec_rep_msg_to_note(msg);
182  M0_LOG(M0_DEBUG, "pool_fid"FID_F"PVER fid"FID_F"note length:%d",
183  FID_P(&fhr->fhr_fid),
184  FID_P(&fhr->fhr_pmach->pm_pver->pv_id),
185  nvec.nv_nr);
188  m0_free(fhr);
189 }
190 
191 M0_INTERNAL void m0_ha_fvec_req_handler(struct m0_ha_fvec_handler *hfh,
192  const struct m0_ha_msg *msg,
193  struct m0_ha_link *hl)
194 {
195  int rc;
196  /* This code is never expected to get exercised in production
197  * environment. It's a place holder to placate various UT's that
198  * indirectly send ha message to fetch failure vector.
199  */
201  M0_PRE(hl != NULL);
203  fvec_msg_cookie_get(msg), hl,
205  M0_ASSERT(rc == 0);
206 }
207 
208 M0_INTERNAL int m0_ha_failvec_fetch(const struct m0_fid *pool_fid,
209  struct m0_poolmach *pmach,
210  struct m0_chan *chan)
211 {
212  struct m0_cookie req_cookie;
213  int rc;
214 
215  M0_PRE(pool_fid != NULL && pmach != NULL && chan != NULL);
216 
217  if (M0_FI_ENABLED("kernel-ut-no-ha")) {
219  return M0_RC(0);
220  }
221  rc = m0_ha_fvec_handler_add(m0_get()->i_fvec_handler,
222  pool_fid, pmach, chan, &req_cookie);
223  if (rc != 0)
224  return M0_RC(rc);
225  rc = m0_ha_msg_fvec_send(pool_fid, &req_cookie, m0_get()->i_ha_link,
227  return M0_RC(rc);
228 }
229 
230 static void ha_ut_fvec_reply_populate(struct m0_ha_msg *msg)
231 {
232  struct m0_ha_note *note;
233  uint32_t nv_nr = 10;
234  uint32_t key;
235  uint32_t states[] = {M0_NC_FAILED, M0_NC_REPAIR,
237  m0_time_t seed;
238 
239  seed = m0_time_now();
240  note = msg->hm_data.u.hed_fvec_rep.mfp_vec.hmna_arr;
241  for (key = 0; key < nv_nr; ++key) {
242  note[key].no_id = M0_FID_TINIT('d', 1, key);
243  if (key < nv_nr / 2)
244  note[key].no_state = M0_NC_FAILED;
245  else
247  &seed)];
248  }
249  msg->hm_data.u.hed_fvec_rep.mfp_nr = nv_nr;
250 }
251 
252 static void ha_msg_fvec_build(struct m0_ha_msg *msg,
253  const struct m0_fid *pool_fid,
254  struct m0_ha_link *hl)
255 {
256  struct m0_reqh *reqh = hl->hln_cfg.hlc_reqh;
257  struct m0_pool *pool;
258  struct m0_pooldev *pd;
259  struct m0_ha_note *note;
260  uint32_t note_nr = 0;
261 
262  pool = m0_pool_find(reqh->rh_pools, pool_fid);
263  M0_ASSERT(pool != NULL);
264  note = msg->hm_data.u.hed_fvec_rep.mfp_vec.hmna_arr;
265  m0_tl_for(pool_failed_devs, &pool->po_failed_devices, pd) {
266  M0_LOG(M0_DEBUG, "adding nvec for "FID_F" state: %d",
267  FID_P(&pd->pd_id), pd->pd_state);
268  note[note_nr].no_id = pd->pd_id;
269  note[note_nr].no_state = pd->pd_state;
270  M0_CNT_INC(note_nr);
271  } m0_tl_endfor;
272  msg->hm_data.u.hed_fvec_rep.mfp_nr = note_nr;
273 }
274 
275 M0_INTERNAL int m0_ha_msg_fvec_send(const struct m0_fid *pool_fid,
276  const struct m0_cookie *cookie,
277  struct m0_ha_link *hl,
278  uint32_t type)
279 {
280  struct m0_ha_msg *msg;
281  uint64_t tag;
282 
285  M0_PRE(hl != NULL);
286 
287  M0_ALLOC_PTR(msg);
288  if (msg == NULL)
289  return M0_ERR(-ENOMEM);
290  msg->hm_data.hed_type = type;
292  msg->hm_data.u.hed_fvec_req.mfq_pool = *pool_fid;
293  msg->hm_data.u.hed_fvec_req.mfq_cookie = *cookie;
294  } else {
295  msg->hm_data.u.hed_fvec_rep.mfp_pool = *pool_fid;
296  msg->hm_data.u.hed_fvec_rep.mfp_cookie = *cookie;
297  }
298 
300  if (M0_FI_ENABLED("non-trivial-fvec"))
302  else {
303  /*
304  * Failur vector is returned by Motr procress only
305  * in system tests by a m0d that mocks Halon.
306  * In production failure vector must be fetched from
307  * Halon only. Here we do not guard against the
308  * concurrent device transtions and sending the failure
309  * vector.
310  */
311  ha_msg_fvec_build(msg, pool_fid, hl);
312  }
313  }
314  m0_ha_link_send(hl, msg, &tag);
315  m0_free(msg);
316  return M0_RC(0);
317 }
318 
319 #undef M0_TRACE_SUBSYSTEM
uint64_t hed_type
Definition: msg.h:88
#define M0_PRE(cond)
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
#define NULL
Definition: misc.h:38
struct m0_pool_version * pm_pver
Definition: pool_machine.h:172
static uint64_t tag(uint8_t code, uint64_t id)
Definition: addb2.c:1047
uint64_t m0_time_t
Definition: time.h:37
#define M0_LOG(level,...)
Definition: trace.h:167
static uint32_t fvec_msg_type(const struct m0_ha_msg *msg)
Definition: failvec.c:74
struct m0_bufvec data
Definition: di.c:40
struct m0_fid fhr_fid
Definition: failvec.c:43
struct m0_ha_msg_data hm_data
Definition: msg.h:122
struct m0_mutex hfh_lock
Definition: failvec.h:61
struct m0_ha_fvec_handler * i_fvec_handler
Definition: instance.h:112
M0_INTERNAL struct m0 * m0_get(void)
Definition: instance.c:41
static const struct m0_ha_note * fvec_rep_msg_to_note(const struct m0_ha_msg *msg)
Definition: failvec.c:63
#define container_of(ptr, type, member)
Definition: misc.h:33
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
M0_INTERNAL int m0_ha_failvec_fetch(const struct m0_fid *pool_fid, struct m0_poolmach *pmach, struct m0_chan *chan)
Definition: failvec.c:208
#define m0_tl_endfor
Definition: tlist.h:700
M0_INTERNAL void m0_ha_link_send(struct m0_ha_link *hl, const struct m0_ha_msg *msg, uint64_t *tag)
Definition: link.c:556
return M0_RC(rc)
struct m0_tl hfh_fvreq
Definition: failvec.h:60
#define M0_ENTRY(...)
Definition: trace.h:170
static uint32_t fvec_rep_msg_vec_len(const struct m0_ha_msg *msg)
Definition: failvec.c:51
#define M0_ERR_INFO(rc, fmt,...)
Definition: trace.h:215
int32_t nv_nr
Definition: note.h:196
return M0_ERR(-EOPNOTSUPP)
static void ha_fvec_handler_msg(struct m0_ha_handler *hh, struct m0_ha *ha, struct m0_ha_link *hl, struct m0_ha_msg *msg, uint64_t tag, void *data)
Definition: failvec.c:83
struct m0_chan * fhr_chan
Definition: failvec.c:40
M0_INTERNAL uint64_t m0_rnd(uint64_t max, uint64_t *seed)
Definition: misc.c:115
static int key
Definition: locality.c:283
#define M0_FID_TINIT(type, container, key)
Definition: fid.h:90
struct m0_ha_dispatcher * hfh_dispatcher
Definition: failvec.h:63
struct m0_fid pv_id
Definition: pool.h:113
#define M0_ASSERT(cond)
static const struct m0_fid * fvec_msg_to_pool(const struct m0_ha_msg *msg)
Definition: failvec.c:69
m0_time_t m0_time_now(void)
Definition: time.c:134
struct m0_poolmach * fhr_pmach
Definition: failvec.c:45
M0_INTERNAL void m0_poolmach_failvec_apply(struct m0_poolmach *pm, const struct m0_ha_nvec *nvec)
Definition: pool_machine.c:999
static void ha_msg_fvec_build(struct m0_ha_msg *msg, const struct m0_fid *pool_fid, struct m0_ha_link *hl)
Definition: failvec.c:252
M0_TL_DEFINE(ha_fvreq, static, struct ha_fvec_handler_request)
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
Definition: msg.h:115
M0_INTERNAL int m0_ha_msg_fvec_send(const struct m0_fid *pool_fid, const struct m0_cookie *cookie, struct m0_ha_link *hl, uint32_t type)
Definition: failvec.c:275
Definition: reqh.h:94
struct m0_fid pd_id
Definition: pool.h:428
Definition: chan.h:229
M0_INTERNAL void m0_ha_dispatcher_attach(struct m0_ha_dispatcher *hd, struct m0_ha_handler *hh)
Definition: dispatcher.c:219
M0_INTERNAL void m0_ha_fvec_req_handler(struct m0_ha_fvec_handler *hfh, const struct m0_ha_msg *msg, struct m0_ha_link *hl)
Definition: failvec.c:191
#define FID_P(f)
Definition: fid.h:77
struct m0_fid no_id
Definition: note.h:180
M0_INTERNAL void m0_chan_signal_lock(struct m0_chan *chan)
Definition: chan.c:165
Definition: ha.h:289
static struct m0_pool pool
Definition: iter_ut.c:58
struct m0_reqh reqh
Definition: rm_foms.c:48
struct m0_tlink fhr_tlink
Definition: failvec.c:41
union m0_ha_msg_data::@212 u
M0_INTERNAL void m0_ha_dispatcher_detach(struct m0_ha_dispatcher *hd, struct m0_ha_handler *hh)
Definition: dispatcher.c:225
#define M0_CNT_INC(cnt)
Definition: arith.h:226
static struct m0_chan chan[RDWR_REQUEST_MAX]
#define M0_FI_ENABLED(tag)
Definition: finject.h:231
Definition: fid.h:38
M0_INTERNAL struct m0_pool * m0_pool_find(struct m0_pools_common *pc, const struct m0_fid *pool)
Definition: pool.c:257
#define M0_IS0(obj)
Definition: misc.h:70
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
struct m0_pools_common * rh_pools
Definition: reqh.h:118
M0_TL_DESCR_DEFINE(ha_fvreq, "failure-vec-req", static, struct ha_fvec_handler_request, fhr_tlink, fhr_magic, 20, 21)
Definition: pool.h:80
struct m0_ha_handler hfh_handler
Definition: failvec.h:62
M0_INTERNAL int m0_ha_fvec_handler_add(struct m0_ha_fvec_handler *hfh, const struct m0_fid *pool_fid, struct m0_poolmach *pool_mach, struct m0_chan *chan, struct m0_cookie *cookie)
Definition: failvec.c:135
int32_t nv_nr
Definition: note.h:331
int type
Definition: dir.c:1031
M0_INTERNAL int m0_ha_fvec_handler_init(struct m0_ha_fvec_handler *hfh, struct m0_ha_dispatcher *hd)
Definition: failvec.c:108
struct m0_ha_note * nv_note
Definition: note.h:197
#define m0_tl_for(name, head, obj)
Definition: tlist.h:695
void m0_free(void *data)
Definition: memory.c:146
void * hh_data
Definition: dispatcher.h:70
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
static struct m0_sm_state_descr states[C_NR]
Definition: sm.c:512
static void ha_ut_fvec_reply_populate(struct m0_ha_msg *msg)
Definition: failvec.c:230
M0_INTERNAL void m0_ha_fvec_rep_handler(struct m0_ha_fvec_handler *hfh, const struct m0_ha_msg *msg)
Definition: failvec.c:165
M0_INTERNAL void m0_ha_fvec_handler_fini(struct m0_ha_fvec_handler *hfh)
Definition: failvec.c:126
static const struct m0_cookie * fvec_msg_cookie_get(const struct m0_ha_msg *msg)
Definition: failvec.c:57
#define FID_F
Definition: fid.h:75
Definition: idx_mock.c:47
uint32_t no_state
Definition: note.h:182
struct m0_tl po_failed_devices
Definition: pool.h:93