Motr  M0
finject.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-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 #ifdef ENABLE_FAULT_INJECTION
24 
25 #ifdef __KERNEL__
26 #include <linux/kernel.h> /* snprintf */
27 #else
28 #include <stdio.h> /* snprintf */
29 #endif
30 
31 #include "lib/errno.h" /* ENOMEM */
32 #include "lib/memory.h" /* M0_ALLOC_ARR */
33 #include "lib/mutex.h" /* m0_mutex */
34 #include "lib/misc.h" /* <linux/string.h> <string.h> for strcmp */
35 #include "lib/assert.h" /* M0_ASSERT */
36 #include "lib/tlist.h"
37 #include "lib/finject.h"
38 #include "lib/finject_internal.h"
39 #include "motr/magic.h"
40 
41 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_LIB
42 #include "lib/trace.h"
43 
44 enum {
45  FI_STATES_ARRAY_SIZE = 64 * 1024,
46 };
47 
51 
52 struct fi_dynamic_id {
54  uint64_t fdi_magic;
55  char *fdi_str;
56 };
57 
58 M0_TL_DESCR_DEFINE(fi_dynamic_ids, "finject_dynamic_id", static,
59  struct fi_dynamic_id, fdi_tlink, fdi_magic,
62 
74 static struct m0_tl fi_dynamic_ids;
75 
76 /* keep these long strings on a single line for easier editing */
77 const char *m0_fi_states_headline[] = {
78 " Idx | Enb |TotHits|TotTrig|Hits|Trig| Type | Data | Module | File name | Line | Func name | Tag\n",
79 "-----+-----+-------+-------+----+----+----------+----------+--------+----------------------------------------+------+-----------------------------------+----------\n",
80 };
81 M0_EXPORTED(m0_fi_states_headline);
82 
84 " %-3u %c %-7u %-7u %-4u %-4u %-10s %-10s %-8s %-40s %-4u %-35s %s\n";
85 M0_EXPORTED(m0_fi_states_print_format);
86 
87 
88 M0_INTERNAL const struct m0_fi_fpoint_state *m0_fi_states_get(void)
89 {
90  return fi_states;
91 }
92 M0_EXPORTED(m0_fi_states_get);
93 
94 M0_INTERNAL uint32_t m0_fi_states_get_free_idx(void)
95 {
96  return fi_states_free_idx;
97 }
98 M0_EXPORTED(m0_fi_states_get_free_idx);
99 
100 static inline uint32_t fi_state_idx(const struct m0_fi_fpoint_state *s)
101 {
102  return s - fi_states;
103 }
104 
106 {
107  si->si_idx = 0;
108  si->si_enb = 'n';
109  si->si_total_hit_cnt = 0;
110  si->si_total_trigger_cnt = 0;
111  si->si_hit_cnt = 0;
112  si->si_trigger_cnt = 0;
113  si->si_type = "";
114  si->si_module = "";
115  si->si_file = "";
116  si->si_func = "";
117  si->si_tag = "";
118  si->si_line_num = 0;
119 
120  M0_SET_ARR0(si->si_data);
121 }
122 
123 M0_INTERNAL void m0_fi_states_get_state_info(const struct m0_fi_fpoint_state *s,
124  struct m0_fi_fpoint_state_info *si)
125 {
126  const struct m0_fi_fault_point *fp;
127 
129 
130  si->si_idx = fi_state_idx(s);
131  si->si_func = s->fps_id.fpi_func;
132  si->si_tag = s->fps_id.fpi_tag;
133  si->si_total_hit_cnt = s->fps_total_hit_cnt;
134  si->si_total_trigger_cnt = s->fps_total_trigger_cnt;
135  fp = s->fps_fp;
136 
137  /*
138  * fp can be NULL if fault point was enabled but had not been registered
139  * yet
140  */
141  if (fp != NULL) {
142  si->si_module = fp->fp_module;
143  si->si_file = m0_short_file_name(fp->fp_file);
144  si->si_line_num = fp->fp_line_num;
145  }
146 
147  if (fi_state_enabled(s)) {
148  si->si_enb = 'y';
149  si->si_type = m0_fi_fpoint_type_name(s->fps_data.fpd_type);
150  switch (s->fps_data.fpd_type) {
151  case M0_FI_OFF_N_ON_M:
152  snprintf(si->si_data, sizeof si->si_data, "n=%u,m=%u",
153  s->fps_data.u.s1.fpd_n,
154  s->fps_data.u.s1.fpd_m);
155  break;
156  case M0_FI_RANDOM:
157  snprintf(si->si_data, sizeof si->si_data, "p=%u",
158  s->fps_data.u.fpd_p);
159  break;
160  default:
161  break; /* leave data string empty */
162  }
163  si->si_hit_cnt = s->fps_data.fpd_hit_cnt;
164  si->si_trigger_cnt = s->fps_data.fpd_trigger_cnt;
165  }
166 
167  return;
168 }
169 M0_EXPORTED(m0_fi_states_get_state_info);
170 
171 M0_INTERNAL int m0_fi_add_dyn_id(char *str)
172 {
173  struct fi_dynamic_id *fdi;
174 
175  M0_ALLOC_PTR(fdi);
176  if (fdi == NULL)
177  return M0_ERR(-ENOMEM);
178 
179  m0_tlink_init(&fi_dynamic_ids_tl, &fdi->fdi_tlink);
180  fdi->fdi_str = str;
181  m0_tlist_add(&fi_dynamic_ids_tl, &fi_dynamic_ids, &fdi->fdi_tlink);
182 
183  return 0;
184 }
185 M0_EXPORTED(m0_fi_add_dyn_id);
186 
187 static void fi_dynamic_ids_fini(void)
188 {
189  struct fi_dynamic_id *entry;
190 
192  m0_free(entry->fdi_str);
193  m0_free(entry);
194  }
195 
196  m0_tlist_fini(&fi_dynamic_ids_tl, &fi_dynamic_ids);
197 }
198 
199 M0_INTERNAL void fi_states_init(void)
200 {
201  m0_tlist_init(&fi_dynamic_ids_tl, &fi_dynamic_ids);
202 }
203 
204 M0_INTERNAL void fi_states_fini(void)
205 {
206  int i;
207 
208  for (i = 0; i < fi_states_free_idx; ++i)
209  m0_mutex_fini(&fi_states[i].fps_mutex);
210 
212 }
213 
223 static inline bool fi_fpoint_id_eq(const struct m0_fi_fpoint_id *id1,
224  const struct m0_fi_fpoint_id *id2)
225 {
226  return strcmp(id1->fpi_func, id2->fpi_func) == 0 &&
227  strcmp(id1->fpi_tag, id2->fpi_tag) == 0;
228 }
229 
240 static
242 {
243  int i;
244 
245  for (i = 0; i < fi_states_free_idx; ++i)
246  if (fi_fpoint_id_eq(&fi_states[i].fps_id, fp_id))
247  return &fi_states[i];
248 
249  return NULL;
250 }
251 
258 static inline
260 {
261  struct m0_fi_fpoint_state *state;
262 
264  state = __fi_state_find(fp_id);
266 
267  return state;
268 }
269 
274 {
275  struct m0_fi_fpoint_state *state;
276 
277  state = &fi_states[fi_states_free_idx];
280  m0_mutex_init(&state->fps_mutex);
281  state->fps_id = *id;
282 
283  return state;
284 }
285 
289 static bool fi_state_always(struct m0_fi_fpoint_state *fps)
290 {
291  return true;
292 }
293 
294 static void fi_disable_state(struct m0_fi_fpoint_state *fps);
295 
299 static bool fi_state_oneshot(struct m0_fi_fpoint_state *fps)
300 {
301  fi_disable_state(fps);
302  return true;
303 }
304 
305 M0_INTERNAL uint32_t fi_random(void);
306 
310 static bool fi_state_random(struct m0_fi_fpoint_state *fps)
311 {
312  return fps->fps_data.u.fpd_p >= fi_random();
313 }
314 
318 static bool fi_state_off_n_on_m(struct m0_fi_fpoint_state *fps)
319 {
320  struct m0_fi_fpoint_data *data = &fps->fps_data;
321  bool enabled = false;
322 
323  m0_mutex_lock(&fps->fps_mutex);
324 
325  data->u.s1.fpd___n_cnt++;
326  if (data->u.s1.fpd___n_cnt > data->u.s1.fpd_n) {
327  enabled = true;
328  data->u.s1.fpd___m_cnt++;
329  if (data->u.s1.fpd___m_cnt >= data->u.s1.fpd_m) {
330  data->u.s1.fpd___n_cnt = 0;
331  data->u.s1.fpd___m_cnt = 0;
332  }
333  }
334 
335  m0_mutex_unlock(&fps->fps_mutex);
336 
337  return enabled;
338 }
339 
343 static bool fi_state_user_func(struct m0_fi_fpoint_state *fps)
344 {
345  return fps->fps_data.u.s2.fpd_trigger_func(fps->fps_data.u.s2.fpd_private);
346 }
347 
348 static const char *fi_type_names[M0_FI_TYPES_NR] = {
349  [M0_FI_ALWAYS] = "always",
350  [M0_FI_ONESHOT] = "oneshot",
351  [M0_FI_RANDOM] = "random",
352  [M0_FI_OFF_N_ON_M] = "off_n_on_m",
353  [M0_FI_FUNC] = "user_func",
354  [M0_FI_INVALID_TYPE] = "",
355 };
356 
357 M0_INTERNAL const char *m0_fi_fpoint_type_name(enum m0_fi_fpoint_type type)
358 {
360  return fi_type_names[type];
361 }
362 M0_EXPORTED(m0_fi_fpoint_type_name);
363 
365  *type_name)
366 {
367  int i;
368 
369  for (i = 0; i < M0_FI_TYPES_NR; i++)
370  if (strcmp(fi_type_names[i], type_name) == 0)
371  return i;
372 
373  return M0_FI_INVALID_TYPE;
374 }
375 M0_EXPORTED(m0_fi_fpoint_type_from_str);
376 
383 };
384 
388 static void fi_enable_state(struct m0_fi_fpoint_state *fp_state,
389  const struct m0_fi_fpoint_data *fp_data)
390 {
392 
393  m0_mutex_lock(&fp_state->fps_mutex);
394 
395  if (fp_data != NULL)
396  fp_state->fps_data = *fp_data;
397 
398  if (fp_state->fps_data.fpd_type == M0_FI_OFF_N_ON_M) {
399  fp_state->fps_data.u.s1.fpd___n_cnt = 0;
400  fp_state->fps_data.u.s1.fpd___m_cnt = 0;
401  }
402 
403  fp_state->fps_trigger_func = fi_trigger_funcs[fp_data->fpd_type];
404 
405  m0_mutex_unlock(&fp_state->fps_mutex);
406 }
407 
411 static void fi_disable_state(struct m0_fi_fpoint_state *fps)
412 {
413  static const struct m0_fi_fpoint_data zero_data;
414 
415  m0_mutex_lock(&fps->fps_mutex);
416 
417  fps->fps_trigger_func = NULL;
418  fps->fps_data = zero_data;
419 
420  m0_mutex_unlock(&fps->fps_mutex);
421 }
422 
424 {
425  struct m0_fi_fpoint_state *state;
426  struct m0_fi_fpoint_id id = {
427  .fpi_func = fp->fp_func,
428  .fpi_tag = fp->fp_tag,
429  };
430 
432 
433  state = __fi_state_find(&id);
434  if (state == NULL)
435  state = fi_state_alloc(&id);
436 
437  /* Link state and fault point structures to each other */
438  state->fps_fp = fp;
439  fp->fp_state = state;
440 
442 }
443 M0_EXPORTED(m0_fi_register);
444 
446 {
447  bool enabled;
448 
449  enabled = fi_state_enabled(fps) ? fps->fps_trigger_func(fps) : false;
450  if (enabled) {
451  fps->fps_total_trigger_cnt++;
452  fps->fps_data.fpd_trigger_cnt++;
453  }
454  if (fi_state_enabled(fps))
455  fps->fps_data.fpd_hit_cnt++;
456  fps->fps_total_hit_cnt++;
457 
458  return enabled;
459 }
460 M0_EXPORTED(m0_fi_enabled);
461 
462 M0_INTERNAL void m0_fi_enable_generic(const char *fp_func, const char *fp_tag,
463  const struct m0_fi_fpoint_data *fp_data)
464 {
465  struct m0_fi_fpoint_state *state;
466  struct m0_fi_fpoint_id id = {
467  .fpi_func = fp_func,
468  .fpi_tag = fp_tag,
469  };
470 
471  M0_PRE(fp_func != NULL && fp_tag != NULL);
472 
474 
475  state = __fi_state_find(&id);
476  if (state == NULL)
477  state = fi_state_alloc(&id);
478 
479  fi_enable_state(state, fp_data);
480 
482 }
483 M0_EXPORTED(m0_fi_enable_generic);
484 
485 M0_INTERNAL void m0_fi_disable(const char *fp_func, const char *fp_tag)
486 {
487  struct m0_fi_fpoint_state *state;
488  struct m0_fi_fpoint_id id = {
489  .fpi_func = fp_func,
490  .fpi_tag = fp_tag
491  };
492 
493  state = fi_state_find(&id);
494  M0_ASSERT(state != NULL);
495 
496  fi_disable_state(state);
497 }
498 M0_EXPORTED(m0_fi_disable);
499 
500 #endif /* ENABLE_FAULT_INJECTION */
501 
502 #undef M0_TRACE_SUBSYSTEM
503 
504 /*
505  * Local variables:
506  * c-indentation-style: "K&R"
507  * c-basic-offset: 8
508  * tab-width: 8
509  * fill-column: 80
510  * scroll-step: 1
511  * End:
512  */
uint64_t id
Definition: cob.h:2380
static const char * fi_type_names[M0_FI_TYPES_NR]
Definition: finject.c:348
uint32_t fpd_p
Definition: finject.h:174
struct m0_fi_fpoint_data::@247::@249 s2
#define M0_PRE(cond)
static bool fi_fpoint_id_eq(const struct m0_fi_fpoint_id *id1, const struct m0_fi_fpoint_id *id2)
Definition: finject.c:223
M0_INTERNAL void m0_mutex_unlock(struct m0_mutex *mutex)
Definition: mutex.c:66
uint64_t fdi_magic
Definition: finject.c:54
struct m0_fi_fpoint_id fps_id
static void fi_enable_state(struct m0_fi_fpoint_state *fp_state, const struct m0_fi_fpoint_data *fp_data)
Definition: finject.c:388
#define NULL
Definition: misc.h:38
uint32_t fpd_trigger_cnt
Definition: finject.h:185
static bool fi_state_always(struct m0_fi_fpoint_state *fps)
Definition: finject.c:289
M0_INTERNAL void m0_tlist_add(const struct m0_tl_descr *d, struct m0_tl *list, void *obj)
Definition: tlist.c:125
fp_state_func_t fps_trigger_func
M0_INTERNAL const struct m0_fi_fpoint_state * m0_fi_states_get(void)
Definition: finject.c:88
static struct m0_fi_fpoint_state * __fi_state_find(const struct m0_fi_fpoint_id *fp_id)
Definition: finject.c:241
static struct m0_fi_fpoint_state * fi_state_alloc(struct m0_fi_fpoint_id *id)
Definition: finject.c:273
M0_INTERNAL enum m0_fi_fpoint_type m0_fi_fpoint_type_from_str(const char *type_name)
Definition: finject.c:364
struct m0_fi_fpoint_data::@247::@248 s1
struct m0_bufvec data
Definition: di.c:40
M0_INTERNAL void m0_tlist_init(const struct m0_tl_descr *d, struct m0_tl *list)
Definition: tlist.c:46
uint32_t fpd_hit_cnt
Definition: finject.h:180
M0_INTERNAL void m0_tlist_fini(const struct m0_tl_descr *d, struct m0_tl *list)
Definition: tlist.c:53
M0_INTERNAL void m0_mutex_lock(struct m0_mutex *mutex)
Definition: mutex.c:49
void m0_fi_register(struct m0_fi_fault_point *fp)
Definition: finject.c:423
static struct m0_tl fi_dynamic_ids
Definition: finject.c:74
M0_TL_DEFINE(fi_dynamic_ids, static, struct fi_dynamic_id)
M0_INTERNAL const char * m0_short_file_name(const char *fname)
Definition: misc.c:212
M0_TL_DESCR_DEFINE(fi_dynamic_ids, "finject_dynamic_id", static, struct fi_dynamic_id, fdi_tlink, fdi_magic, M0_FI_DYNAMIC_ID_MAGIC, M0_FI_DYNAMIC_ID_HEAD_MAGIC)
uint32_t fps_total_trigger_cnt
int i
Definition: dir.c:1033
#define M0_SET_ARR0(arr)
Definition: misc.h:72
return M0_ERR(-EOPNOTSUPP)
static void fi_state_info_init(struct m0_fi_fpoint_state_info *si)
Definition: finject.c:105
static bool fi_state_random(struct m0_fi_fpoint_state *fps)
Definition: finject.c:310
#define m0_tl_teardown(name, head, obj)
Definition: tlist.h:708
M0_INTERNAL void m0_fi_disable(const char *fp_func, const char *fp_tag)
Definition: finject.c:485
enum m0_fi_fpoint_type fpd_type
Definition: finject.h:132
static struct m0_fi_fpoint_state * fi_state_find(struct m0_fi_fpoint_id *fp_id)
Definition: finject.c:259
#define M0_ASSERT(cond)
static bool fi_state_user_func(struct m0_fi_fpoint_state *fps)
Definition: finject.c:343
M0_INTERNAL uint32_t fi_random(void)
Definition: finject_init.c:56
Definition: tlist.h:251
union m0_fi_fpoint_data::@247 u
M0_INTERNAL void fi_states_init(void)
Definition: finject.c:199
M0_INTERNAL void m0_mutex_init(struct m0_mutex *mutex)
Definition: mutex.c:35
M0_INTERNAL int m0_fi_add_dyn_id(char *str)
Definition: finject.c:171
uint32_t fi_states_free_idx
Definition: finject.c:49
M0_INTERNAL const char * m0_fi_fpoint_type_name(enum m0_fi_fpoint_type type)
Definition: finject.c:357
const char m0_fi_states_print_format[]
Definition: finject.c:83
struct m0_fi_fpoint_data fps_data
bool(* fp_state_func_t)(struct m0_fi_fpoint_state *fps)
M0_INTERNAL void m0_tlink_init(const struct m0_tl_descr *d, void *obj)
Definition: tlist.c:63
const char * fpi_tag
M0_INTERNAL uint32_t m0_fi_states_get_free_idx(void)
Definition: finject.c:94
M0_INTERNAL void m0_fi_enable_generic(const char *fp_func, const char *fp_tag, const struct m0_fi_fpoint_data *fp_data)
Definition: finject.c:462
static const fp_state_func_t fi_trigger_funcs[M0_FI_TYPES_NR]
Definition: finject.c:377
static bool fi_state_enabled(const struct m0_fi_fpoint_state *state)
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
static bool fi_state_off_n_on_m(struct m0_fi_fpoint_state *fps)
Definition: finject.c:318
const char * fpi_func
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
bool m0_fi_enabled(struct m0_fi_fpoint_state *fps)
Definition: finject.c:445
#define IS_IN_ARRAY(idx, array)
Definition: misc.h:311
M0_INTERNAL void fi_states_fini(void)
Definition: finject.c:204
struct m0_fi_fault_point * fps_fp
struct m0_mutex fi_states_mutex
Definition: finject.c:50
struct m0_tlink fdi_tlink
Definition: finject.c:53
static bool fi_state_oneshot(struct m0_fi_fpoint_state *fps)
Definition: finject.c:299
M0_INTERNAL void m0_fi_states_get_state_info(const struct m0_fi_fpoint_state *s, struct m0_fi_fpoint_state_info *si)
Definition: finject.c:123
m0_fi_fpoint_type
Definition: finject.h:93
const char * m0_fi_states_headline[]
Definition: finject.c:77
Definition: rcv_session.c:58
static void fi_dynamic_ids_fini(void)
Definition: finject.c:187
int type
Definition: dir.c:1031
struct m0_mutex fps_mutex
void m0_free(void *data)
Definition: memory.c:146
Definition: mutex.h:47
static struct m0_addb2_source * s
Definition: consumer.c:39
#define ARRAY_SIZE(a)
Definition: misc.h:45
static struct sync_interactions si
Definition: sync.c:121
char * fdi_str
Definition: finject.c:55
static void fi_disable_state(struct m0_fi_fpoint_state *fps)
Definition: finject.c:411
static uint32_t fi_state_idx(const struct m0_fi_fpoint_state *s)
Definition: finject.c:100
struct m0_fi_fpoint_state fi_states[FI_STATES_ARRAY_SIZE]
Definition: finject.c:48