Motr  M0
finject_init.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 
24 #include <stdio.h> /* printf */
25 
26 #ifdef ENABLE_FAULT_INJECTION
27 
28 #include <stdlib.h> /* random */
29 #include <unistd.h> /* getpid */
30 #include <err.h> /* warn */
31 #include <yaml.h>
32 
33 #include "lib/memory.h" /* m0_free */
34 #include "lib/mutex.h" /* m0_mutex */
35 #include "lib/time.h" /* m0_time_now */
36 #include "lib/string.h" /* m0_strdup */
37 #include "lib/errno.h" /* ENOMEM */
38 #include "lib/finject.h"
39 #include "lib/finject_internal.h"
40 
41 
42 M0_INTERNAL int m0_fi_init(void)
43 {
44  unsigned int random_seed;
45 
47 
48  /*
49  * Initialize pseudo random generator, which is used in M0_FI_RANDOM
50  * triggering algorithm
51  */
52  random_seed = m0_time_now() ^ getpid();
53  srandom(random_seed);
54 
56 
57  return 0;
58 }
59 
60 M0_INTERNAL void m0_fi_fini(void)
61 {
64 }
65 
66 enum {
68 };
69 
73 M0_INTERNAL uint32_t fi_random(void)
74 {
75  return (double)random() / RAND_MAX * FI_RAND_PROB_SCALE;
76 }
77 
78 M0_INTERNAL void m0_fi_print_info(void)
79 {
80  int i;
81 
82  const struct m0_fi_fpoint_state *state;
84 
85  printf("%s", m0_fi_states_headline[0]);
86  printf("%s", m0_fi_states_headline[1]);
87 
88  for (i = 0; i < m0_fi_states_get_free_idx(); ++i) {
89 
90  state = &m0_fi_states_get()[i];
92 
94  si.si_idx, si.si_enb, si.si_total_hit_cnt,
95  si.si_total_trigger_cnt, si.si_hit_cnt,
96  si.si_trigger_cnt, si.si_type, si.si_data, si.si_module,
97  si.si_file, si.si_line_num, si.si_func, si.si_tag);
98  }
99 
100  return;
101 }
102 
103 M0_INTERNAL int m0_fi_enable_fault_point(const char *str)
104 {
105  int rc = 0;
106  int i;
107  char *s;
108  char *token;
109  char *subtoken;
110  char *token_saveptr = NULL;
111  char *subtoken_saveptr = NULL;
112 
113  const char *func;
114  const char *tag;
115  const char *type;
116  const char *data1;
117  const char *data2;
118  const char **fp_map[] = { &func, &tag, &type, &data1, &data2 };
119 
120  struct m0_fi_fpoint_data data = { 0 };
121 
122  if (str == NULL)
123  return 0;
124 
125  s = m0_strdup(str);
126  if (s == NULL)
127  return -ENOMEM;
128 
129  while (true) {
130  func = tag = type = data1 = data2 = NULL;
131 
132  token = strtok_r(s, ",", &token_saveptr);
133  if (token == NULL)
134  break;
135 
136  subtoken = token;
137  for (i = 0; i < sizeof fp_map; ++i) {
138  subtoken = strtok_r(token, ":", &subtoken_saveptr);
139  if (subtoken == NULL)
140  break;
141 
142  *fp_map[i] = subtoken;
143 
144  /*
145  * token should be NULL for subsequent strtok_r(3) calls
146  */
147  token = NULL;
148  }
149 
150  if (func == NULL || tag == NULL || type == NULL) {
151  warn("Incorrect fault point specification\n");
152  rc = -EINVAL;
153  goto out;
154  }
155 
157  if (data.fpd_type == M0_FI_INVALID_TYPE) {
158  warn("Incorrect fault point type '%s'\n", type);
159  rc = -EINVAL;
160  goto out;
161  }
162 
163  if (data.fpd_type == M0_FI_RANDOM) {
164  if (data1 == NULL) {
165  warn("No probability was specified"
166  " for 'random' FP type\n");
167  rc = -EINVAL;
168  goto out;
169  }
170  data.u.fpd_p = atoi(data1);
171  } else if (data.fpd_type == M0_FI_OFF_N_ON_M) {
172  if (data1 == NULL || data2 == NULL) {
173  warn("No N or M was specified"
174  " for 'off_n_on_m' FP type\n");
175  rc = -EINVAL;
176  goto out;
177  }
178  data.u.s1.fpd_n = atoi(data1);
179  data.u.s1.fpd_m = atoi(data2);
180  }
181 
182  m0_fi_enable_generic(func, tag, &data);
183 
184  /* s should be NULL for subsequent strtok_r(3) calls */
185  s = NULL;
186  }
187 out:
188  m0_free(s);
189  return rc;
190 }
191 
192 static inline const char *pair_key(yaml_document_t *doc, yaml_node_pair_t *pair)
193 {
194  return (const char*)yaml_document_get_node(doc, pair->key)->data.scalar.value;
195 }
196 
197 static inline const char *pair_val(yaml_document_t *doc, yaml_node_pair_t *pair)
198 {
199  return (const char*)yaml_document_get_node(doc, pair->value)->data.scalar.value;
200 }
201 
202 static int extract_fpoint_data(yaml_document_t *doc, yaml_node_t *node,
203  const char **func, const char **tag,
204  struct m0_fi_fpoint_data *data)
205 {
206  yaml_node_pair_t *pair;
207 
208  for (pair = node->data.mapping.pairs.start;
209  pair < node->data.mapping.pairs.top; pair++) {
210  const char *key = pair_key(doc, pair);
211  const char *val = pair_val(doc, pair);
212  if (strcmp(key, "func") == 0) {
213  *func = val;
214  } else if (strcmp(key, "tag") == 0) {
215  *tag = val;
216  } else if (strcmp(key, "type") == 0) {
217  data->fpd_type = m0_fi_fpoint_type_from_str(val);
218  if (data->fpd_type == M0_FI_INVALID_TYPE) {
219  warn("Incorrect FP type '%s'\n", val);
220  return -EINVAL;
221  }
222  }
223  else if (strcmp(key, "p") == 0) {
224  data->u.fpd_p = atoi(val);
225  } else if (strcmp(key, "n") == 0) {
226  data->u.s1.fpd_n = atoi(val);
227  } else if (strcmp(key, "m") == 0) {
228  data->u.s1.fpd_m = atoi(val);
229  } else {
230  warn("Incorrect key '%s' in yaml file\n", key);
231  return -EINVAL;
232  }
233  }
234 
235  return 0;
236 }
237 
238 static int process_yaml(yaml_document_t *doc)
239 {
240  int rc;
241  yaml_node_t *node;
242  const char *func = 0;
243  const char *tag = 0;
244 
245  struct m0_fi_fpoint_data data = { 0 };
246 
247  for (node = doc->nodes.start; node < doc->nodes.top; node++)
248  if (node->type == YAML_MAPPING_NODE) {
249  rc = extract_fpoint_data(doc, node, &func, &tag, &data);
250  if (rc != 0)
251  return rc;
252  m0_fi_enable_generic(strdup(func), m0_strdup(tag), &data);
253  }
254 
255  return 0;
256 }
257 
258 M0_INTERNAL int m0_fi_enable_fault_points_from_file(const char *file_name)
259 {
260  int rc = 0;
261  FILE *f;
262  yaml_parser_t parser;
263  yaml_document_t document;
264 
265  f = fopen(file_name, "r");
266  if (f == NULL) {
267  warn("Failed to open fault point yaml file '%s'", file_name);
268  return -ENOENT;
269  }
270 
271  rc = yaml_parser_initialize(&parser);
272  if (rc != 1) {
273  warn("Failed to init yaml parser\n");
274  rc = -EINVAL;
275  goto fclose;
276  }
277 
278  yaml_parser_set_input_file(&parser, f);
279 
280  rc = yaml_parser_load(&parser, &document);
281  if (rc != 1) {
282  warn("Incorrect YAML file\n");
283  rc = -EINVAL;
284  goto pdel;
285  }
286 
287  rc = process_yaml(&document);
288 
289  yaml_document_delete(&document);
290 pdel:
291  yaml_parser_delete(&parser);
292 fclose:
293  fclose(f);
294 
295  return rc;
296 }
297 
298 #else /* ENABLE_FAULT_INJECTION */
299 
300 int m0_fi_enable_fault_point(const char *str)
301 {
302  return 0;
303 }
304 
305 M0_INTERNAL int m0_fi_enable_fault_points_from_file(const char *file_name)
306 {
307  return 0;
308 }
309 
310 M0_INTERNAL int m0_fi_init(void)
311 {
312  return 0;
313 }
314 
315 M0_INTERNAL void m0_fi_fini(void)
316 {
317 }
318 
319 M0_INTERNAL void m0_fi_print_info(void)
320 {
321  fprintf(stderr, "Fault injection is not available, because it was"
322  " disabled during build\n");
323 }
324 
325 #endif /* ENABLE_FAULT_INJECTION */
326 
327 /*
328  * Local variables:
329  * c-indentation-style: "K&R"
330  * c-basic-offset: 8
331  * tab-width: 8
332  * fill-column: 80
333  * scroll-step: 1
334  * End:
335  */
#define m0_strdup(s)
Definition: string.h:43
M0_INTERNAL void m0_fi_print_info(void)
Definition: finject_init.c:78
#define NULL
Definition: misc.h:38
Definition: idx_mock.c:52
static FILE * f
Definition: adieu.c:79
static uint64_t tag(uint8_t code, uint64_t id)
Definition: addb2.c:1047
static struct net_test_cmd_node * node
Definition: commands.c:72
M0_INTERNAL const struct m0_fi_fpoint_state * m0_fi_states_get(void)
Definition: finject.c:88
static const char * pair_val(yaml_document_t *doc, yaml_node_pair_t *pair)
Definition: finject_init.c:197
M0_INTERNAL enum m0_fi_fpoint_type m0_fi_fpoint_type_from_str(const char *type_name)
Definition: finject.c:364
struct m0_bufvec data
Definition: di.c:40
M0_INTERNAL int m0_fi_init(void)
Definition: finject_init.c:40
int i
Definition: dir.c:1033
static const char * pair_key(yaml_document_t *doc, yaml_node_pair_t *pair)
Definition: finject_init.c:192
m0_time_t m0_time_now(void)
Definition: time.c:134
static struct net_test_cmd_node nodes[NTC_MULTIPLE_NODES]
Definition: commands.c:74
parser
Definition: queues.py:206
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
static void token(struct ff2c_context *ctx, struct ff2c_term *term, struct ff2c_token *tok)
Definition: parser.c:66
const char m0_fi_states_print_format[]
Definition: finject.c:83
M0_INTERNAL int m0_fi_enable_fault_point(const char *str)
Definition: finject_init.c:103
M0_INTERNAL uint32_t m0_fi_states_get_free_idx(void)
Definition: finject.c:94
static int extract_fpoint_data(yaml_document_t *doc, yaml_node_t *node, const char **func, const char **tag, struct m0_fi_fpoint_data *data)
Definition: finject_init.c:202
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
M0_INTERNAL void m0_mutex_fini(struct m0_mutex *mutex)
Definition: mutex.c:42
M0_INTERNAL uint32_t fi_random(void)
Definition: finject_init.c:56
Definition: xcode.c:1194
M0_INTERNAL void fi_states_fini(void)
Definition: finject.c:204
struct m0_mutex fi_states_mutex
Definition: finject.c:50
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
const char * m0_fi_states_headline[]
Definition: finject.c:77
static int process_yaml(yaml_document_t *doc)
Definition: finject_init.c:238
#define out(...)
Definition: gen.c:41
int type
Definition: dir.c:1031
M0_INTERNAL void m0_fi_fini(void)
Definition: finject_init.c:47
void m0_free(void *data)
Definition: memory.c:146
static struct m0_addb2_source * s
Definition: consumer.c:39
M0_INTERNAL int m0_fi_enable_fault_points_from_file(const char *file_name)
Definition: finject_init.c:258
int32_t rc
Definition: trigger_fop.h:47
static struct sync_interactions si
Definition: sync.c:121
Definition: idx_mock.c:47