Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2017 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : :
8 : : #include "spdk/env.h"
9 : : #include "spdk/trace.h"
10 : : #include "spdk/log.h"
11 : : #include "spdk/util.h"
12 : :
13 : : struct spdk_trace_flags *g_trace_flags = NULL;
14 : : static struct spdk_trace_register_fn *g_reg_fn_head = NULL;
15 : :
16 : 3562 : SPDK_LOG_REGISTER_COMPONENT(trace)
17 : :
18 : : uint64_t
19 : 580 : spdk_trace_get_tpoint_mask(uint32_t group_id)
20 : : {
21 [ - + ]: 580 : if (group_id >= SPDK_TRACE_MAX_GROUP_ID) {
22 : 0 : SPDK_ERRLOG("invalid group ID %d\n", group_id);
23 : 0 : return 0ULL;
24 : : }
25 : :
26 [ + + ]: 580 : if (g_trace_flags == NULL) {
27 : 0 : return 0ULL;
28 : : }
29 : :
30 [ + - + - : 580 : return g_trace_flags->tpoint_mask[group_id];
+ - + - ]
31 : 29 : }
32 : :
33 : : void
34 : 3520 : spdk_trace_set_tpoints(uint32_t group_id, uint64_t tpoint_mask)
35 : : {
36 [ + + ]: 3520 : if (g_trace_flags == NULL) {
37 : 0 : SPDK_ERRLOG("trace is not initialized\n");
38 : 0 : return;
39 : : }
40 : :
41 [ - + ]: 3520 : if (group_id >= SPDK_TRACE_MAX_GROUP_ID) {
42 : 0 : SPDK_ERRLOG("invalid group ID %d\n", group_id);
43 : 0 : return;
44 : : }
45 : :
46 [ + - + - : 3520 : g_trace_flags->tpoint_mask[group_id] |= tpoint_mask;
+ - + - ]
47 : 1 : }
48 : :
49 : : void
50 : 0 : spdk_trace_clear_tpoints(uint32_t group_id, uint64_t tpoint_mask)
51 : : {
52 [ # # ]: 0 : if (g_trace_flags == NULL) {
53 : 0 : SPDK_ERRLOG("trace is not initialized\n");
54 : 0 : return;
55 : : }
56 : :
57 [ # # ]: 0 : if (group_id >= SPDK_TRACE_MAX_GROUP_ID) {
58 : 0 : SPDK_ERRLOG("invalid group ID %d\n", group_id);
59 : 0 : return;
60 : : }
61 : :
62 [ # # # # : 0 : g_trace_flags->tpoint_mask[group_id] &= ~tpoint_mask;
# # # # ]
63 : 0 : }
64 : :
65 : : uint64_t
66 : 20 : spdk_trace_get_tpoint_group_mask(void)
67 : : {
68 : 20 : uint64_t mask = 0x0;
69 : : int i;
70 : :
71 [ + + + - ]: 340 : for (i = 0; i < SPDK_TRACE_MAX_GROUP_ID; i++) {
72 [ + + ]: 320 : if (spdk_trace_get_tpoint_mask(i) != 0) {
73 [ - + ]: 20 : mask |= (1ULL << i);
74 : 1 : }
75 : 16 : }
76 : :
77 : 20 : return mask;
78 : : }
79 : :
80 : : void
81 : 0 : spdk_trace_set_tpoint_group_mask(uint64_t tpoint_group_mask)
82 : : {
83 : : int i;
84 : :
85 [ # # ]: 0 : if (g_trace_flags == NULL) {
86 : 0 : SPDK_ERRLOG("trace is not initialized\n");
87 : 0 : return;
88 : : }
89 : :
90 [ # # # # ]: 0 : for (i = 0; i < SPDK_TRACE_MAX_GROUP_ID; i++) {
91 [ # # # # ]: 0 : if (tpoint_group_mask & (1ULL << i)) {
92 : 0 : spdk_trace_set_tpoints(i, -1ULL);
93 : 0 : }
94 : 0 : }
95 : 0 : }
96 : :
97 : : void
98 : 0 : spdk_trace_clear_tpoint_group_mask(uint64_t tpoint_group_mask)
99 : : {
100 : : int i;
101 : :
102 [ # # ]: 0 : if (g_trace_flags == NULL) {
103 : 0 : SPDK_ERRLOG("trace is not initialized\n");
104 : 0 : return;
105 : : }
106 : :
107 [ # # # # ]: 0 : for (i = 0; i < SPDK_TRACE_MAX_GROUP_ID; i++) {
108 [ # # # # ]: 0 : if (tpoint_group_mask & (1ULL << i)) {
109 : 0 : spdk_trace_clear_tpoints(i, -1ULL);
110 : 0 : }
111 : 0 : }
112 : 0 : }
113 : :
114 : : struct spdk_trace_register_fn *
115 : 43 : spdk_trace_get_first_register_fn(void)
116 : : {
117 : 43 : return g_reg_fn_head;
118 : : }
119 : :
120 : : struct spdk_trace_register_fn *
121 : 324 : spdk_trace_get_next_register_fn(struct spdk_trace_register_fn *register_fn)
122 : : {
123 [ + - + - ]: 324 : return register_fn->next;
124 : : }
125 : :
126 : : uint64_t
127 : 23 : spdk_trace_create_tpoint_group_mask(const char *group_name)
128 : : {
129 : 23 : uint64_t tpoint_group_mask = 0;
130 : : struct spdk_trace_register_fn *register_fn;
131 : :
132 : 23 : register_fn = spdk_trace_get_first_register_fn();
133 [ + + + + : 23 : if (strcmp(group_name, "all") == 0) {
+ - ]
134 [ + + ]: 24 : while (register_fn) {
135 [ - + # # : 22 : tpoint_group_mask |= (1UL << register_fn->tgroup_id);
# # ]
136 : :
137 : 22 : register_fn = spdk_trace_get_next_register_fn(register_fn);
138 : : }
139 : 0 : } else {
140 [ + + ]: 63 : while (register_fn) {
141 [ + + + + : 63 : if (strcmp(group_name, register_fn->name) == 0) {
+ + + - +
+ ]
142 : 21 : break;
143 : : }
144 : :
145 : 42 : register_fn = spdk_trace_get_next_register_fn(register_fn);
146 : : }
147 : :
148 [ + - ]: 21 : if (register_fn != NULL) {
149 [ + + + - : 21 : tpoint_group_mask |= (1UL << register_fn->tgroup_id);
+ - ]
150 : 1 : }
151 : : }
152 : :
153 : 23 : return tpoint_group_mask;
154 : : }
155 : :
156 : : int
157 : 0 : spdk_trace_enable_tpoint_group(const char *group_name)
158 : : {
159 : 0 : uint64_t tpoint_group_mask = 0;
160 : :
161 [ # # ]: 0 : if (g_trace_flags == NULL) {
162 : 0 : return -1;
163 : : }
164 : :
165 : 0 : tpoint_group_mask = spdk_trace_create_tpoint_group_mask(group_name);
166 [ # # ]: 0 : if (tpoint_group_mask == 0) {
167 : 0 : return -1;
168 : : }
169 : :
170 : 0 : spdk_trace_set_tpoint_group_mask(tpoint_group_mask);
171 : 0 : return 0;
172 : 0 : }
173 : :
174 : : int
175 : 0 : spdk_trace_disable_tpoint_group(const char *group_name)
176 : : {
177 : 0 : uint64_t tpoint_group_mask = 0;
178 : :
179 [ # # ]: 0 : if (g_trace_flags == NULL) {
180 : 0 : return -1;
181 : : }
182 : :
183 : 0 : tpoint_group_mask = spdk_trace_create_tpoint_group_mask(group_name);
184 [ # # ]: 0 : if (tpoint_group_mask == 0) {
185 : 0 : return -1;
186 : : }
187 : :
188 : 0 : spdk_trace_clear_tpoint_group_mask(tpoint_group_mask);
189 : 0 : return 0;
190 : 0 : }
191 : :
192 : : void
193 : 37 : spdk_trace_mask_usage(FILE *f, const char *tmask_arg)
194 : : {
195 : : struct spdk_trace_register_fn *register_fn;
196 : 37 : bool first_group_name = true;
197 : :
198 [ - + - + ]: 37 : fprintf(f, " %s, --tpoint-group <group-name>[:<tpoint_mask>]\n", tmask_arg);
199 [ - + - + ]: 37 : fprintf(f, " group_name - tracepoint group name ");
200 [ - + - + ]: 37 : fprintf(f, "for spdk trace buffers (");
201 : :
202 : 37 : register_fn = g_reg_fn_head;
203 [ + + ]: 182 : while (register_fn) {
204 [ + + + + ]: 145 : if (first_group_name) {
205 [ - + - + ]: 37 : fprintf(f, "%s", register_fn->name);
206 : 37 : first_group_name = false;
207 : 1 : } else {
208 [ - + - + ]: 108 : fprintf(f, ", %s", register_fn->name);
209 : : }
210 [ + - + - ]: 145 : register_fn = register_fn->next;
211 : : }
212 : :
213 [ - + - + ]: 37 : fprintf(f, ", all)\n");
214 [ - + - + ]: 37 : fprintf(f, " tpoint_mask - tracepoint mask for enabling individual");
215 [ - + - + ]: 37 : fprintf(f, " tpoints inside a tracepoint group.");
216 [ - + - + ]: 37 : fprintf(f, " First tpoint inside a group can be");
217 [ - + - + ]: 37 : fprintf(f, " enabled by setting tpoint_mask to 1 (e.g. bdev:0x1).\n");
218 [ - + - + ]: 37 : fprintf(f, " Groups and masks can be combined (e.g.");
219 [ - + - + ]: 37 : fprintf(f, " thread,bdev:0x1).\n");
220 [ - + - + ]: 37 : fprintf(f, " All available tpoints can be found in");
221 [ - + - + ]: 37 : fprintf(f, " /include/spdk_internal/trace_defs.h\n");
222 : 37 : }
223 : :
224 : : void
225 : 9402 : spdk_trace_register_owner(uint8_t type, char id_prefix)
226 : : {
227 : : struct spdk_trace_owner *owner;
228 : :
229 [ + + # # ]: 9402 : assert(type != OWNER_NONE);
230 : :
231 [ + + ]: 9402 : if (g_trace_flags == NULL) {
232 : 0 : SPDK_ERRLOG("trace is not initialized\n");
233 : 0 : return;
234 : : }
235 : :
236 : : /* 'owner' has 256 entries and since 'type' is a uint8_t, it
237 : : * can't overrun the array.
238 : : */
239 [ + - + - : 9402 : owner = &g_trace_flags->owner[type];
+ - ]
240 [ + + + - : 9402 : assert(owner->type == 0);
+ - # # ]
241 : :
242 [ + - + - ]: 9402 : owner->type = type;
243 [ + - + - ]: 9402 : owner->id_prefix = id_prefix;
244 : 339 : }
245 : :
246 : : void
247 : 10134 : spdk_trace_register_object(uint8_t type, char id_prefix)
248 : : {
249 : : struct spdk_trace_object *object;
250 : :
251 [ + + # # ]: 10134 : assert(type != OBJECT_NONE);
252 : :
253 [ + + ]: 10134 : if (g_trace_flags == NULL) {
254 : 0 : SPDK_ERRLOG("trace is not initialized\n");
255 : 0 : return;
256 : : }
257 : :
258 : : /* 'object' has 256 entries and since 'type' is a uint8_t, it
259 : : * can't overrun the array.
260 : : */
261 [ + - + - : 10134 : object = &g_trace_flags->object[type];
+ - ]
262 [ + + + - : 10134 : assert(object->type == 0);
+ - # # ]
263 : :
264 [ + - + - ]: 10134 : object->type = type;
265 [ + - + - ]: 10134 : object->id_prefix = id_prefix;
266 : 390 : }
267 : :
268 : : static void
269 : 151388 : trace_register_description(const struct spdk_trace_tpoint_opts *opts)
270 : : {
271 : : struct spdk_trace_tpoint *tpoint;
272 : : size_t i, max_name_length;
273 : :
274 [ + + + - : 151388 : assert(opts->tpoint_id != 0);
+ - # # ]
275 [ + + + - : 151388 : assert(opts->tpoint_id < SPDK_TRACE_MAX_TPOINT_ID);
+ - # # ]
276 : :
277 [ + + + + : 151388 : if (strnlen(opts->name, sizeof(tpoint->name)) == sizeof(tpoint->name)) {
+ - + + ]
278 [ + - + - ]: 732 : SPDK_ERRLOG("name (%s) too long\n", opts->name);
279 : 51 : }
280 : :
281 [ + - + - : 151388 : tpoint = &g_trace_flags->tpoint[opts->tpoint_id];
+ - + - +
- ]
282 [ + + + - : 151388 : assert(tpoint->tpoint_id == 0);
+ - # # ]
283 : :
284 [ + - + - : 151388 : snprintf(tpoint->name, sizeof(tpoint->name), "%s", opts->name);
+ - ]
285 [ + - + - : 151388 : tpoint->tpoint_id = opts->tpoint_id;
+ - + - ]
286 [ + - + - : 151388 : tpoint->object_type = opts->object_type;
+ - + - ]
287 [ + - + - : 151388 : tpoint->owner_type = opts->owner_type;
+ - + - ]
288 [ + - + - : 151388 : tpoint->new_object = opts->new_object;
+ - + - ]
289 : :
290 : 151388 : max_name_length = sizeof(tpoint->args[0].name);
291 [ + + ]: 330250 : for (i = 0; i < SPDK_TRACE_MAX_ARGS_COUNT; ++i) {
292 [ + + + + : 330250 : if (!opts->args[i].name || opts->args[i].name[0] == '\0') {
+ - + - +
+ + - + -
+ - + - +
- + - +
+ ]
293 : 5919 : break;
294 : : }
295 : :
296 [ + + + - : 178862 : switch (opts->args[i].type) {
+ - + - +
+ - ]
297 : 156343 : case SPDK_TRACE_ARG_TYPE_INT:
298 : : case SPDK_TRACE_ARG_TYPE_PTR:
299 : : /* The integers and pointers have to be exactly 4 or 8 bytes */
300 [ + + + + : 162299 : assert(opts->args[i].size == 4 || opts->args[i].size == 8);
+ - + - +
+ + - + -
+ - + - +
- # # ]
301 : 162299 : break;
302 : 16074 : case SPDK_TRACE_ARG_TYPE_STR:
303 : : /* Strings need to have at least one byte for the NULL terminator */
304 [ + + + - : 16563 : assert(opts->args[i].size > 0);
+ - + - +
- # # ]
305 : 16563 : break;
306 : 0 : default:
307 [ # # ]: 0 : assert(0 && "invalid trace argument type");
308 : : break;
309 : : }
310 : :
311 [ + + + + : 178862 : if (strnlen(opts->args[i].name, max_name_length) == max_name_length) {
+ - + - +
- + - ]
312 [ # # # # : 0 : SPDK_ERRLOG("argument name (%s) is too long\n", opts->args[i].name);
# # # # ]
313 : 0 : }
314 : :
315 [ + - + - : 185307 : snprintf(tpoint->args[i].name, sizeof(tpoint->args[i].name),
+ - + - ]
316 [ + - + - : 178862 : "%s", opts->args[i].name);
+ - + - ]
317 [ + - + - : 178862 : tpoint->args[i].type = opts->args[i].type;
+ - + - +
- + - + -
+ - + - ]
318 [ + - + - : 178862 : tpoint->args[i].size = opts->args[i].size;
+ - + - +
- + - + -
+ - + - ]
319 : 6445 : }
320 : :
321 [ + - + - ]: 151388 : tpoint->num_args = i;
322 : 151388 : }
323 : :
324 : : void
325 : 131203 : spdk_trace_register_description_ext(const struct spdk_trace_tpoint_opts *opts, size_t num_opts)
326 : : {
327 : : size_t i;
328 : :
329 [ + + ]: 131203 : if (g_trace_flags == NULL) {
330 : 0 : SPDK_ERRLOG("trace is not initialized\n");
331 : 0 : return;
332 : : }
333 : :
334 [ + + ]: 282591 : for (i = 0; i < num_opts; ++i) {
335 [ + - ]: 151388 : trace_register_description(&opts[i]);
336 : 5919 : }
337 : 5324 : }
338 : :
339 : : void
340 : 122060 : spdk_trace_register_description(const char *name, uint16_t tpoint_id, uint8_t owner_type,
341 : : uint8_t object_type, uint8_t new_object,
342 : : uint8_t arg1_type, const char *arg1_name)
343 : : {
344 : 147335 : struct spdk_trace_tpoint_opts opts = {
345 : 5055 : .name = name,
346 : 5055 : .tpoint_id = tpoint_id,
347 : 5055 : .owner_type = owner_type,
348 : 5055 : .object_type = object_type,
349 : 5055 : .new_object = new_object,
350 : 15165 : .args = {{
351 : 5055 : .name = arg1_name,
352 : 5055 : .type = arg1_type,
353 : : .size = sizeof(uint64_t)
354 : : }
355 : : }
356 : : };
357 : :
358 : 122060 : spdk_trace_register_description_ext(&opts, 1);
359 : 122060 : }
360 : :
361 : : void
362 : 12458 : spdk_trace_tpoint_register_relation(uint16_t tpoint_id, uint8_t object_type, uint8_t arg_index)
363 : : {
364 : : struct spdk_trace_tpoint *tpoint;
365 : : uint16_t i;
366 : :
367 [ + + # # ]: 12458 : assert(object_type != OBJECT_NONE);
368 [ + + # # ]: 12458 : assert(tpoint_id != OBJECT_NONE);
369 : :
370 [ + + ]: 12458 : if (g_trace_flags == NULL) {
371 : 0 : SPDK_ERRLOG("trace is not initialized\n");
372 : 0 : return;
373 : : }
374 : :
375 : : /* We do not check whether a tpoint_id exists here, because
376 : : * there is no order in which trace definitions are registered.
377 : : * This way we can create relations between tpoint and objects
378 : : * that will be declared later. */
379 [ + - + - : 12458 : tpoint = &g_trace_flags->tpoint[tpoint_id];
+ - ]
380 [ + - ]: 12458 : for (i = 0; i < SPDK_COUNTOF(tpoint->related_objects); ++i) {
381 [ + - + - : 12458 : if (tpoint->related_objects[i].object_type == OBJECT_NONE) {
+ - + - +
- ]
382 [ + - + - : 12458 : tpoint->related_objects[i].object_type = object_type;
+ - + - ]
383 [ + - + - : 12458 : tpoint->related_objects[i].arg_index = arg_index;
+ - + - ]
384 : 12458 : return;
385 : : }
386 : 0 : }
387 : 0 : SPDK_ERRLOG("Unable to register new relation for tpoint %" PRIu16 ", object %" PRIu8 "\n",
388 : : tpoint_id, object_type);
389 : 428 : }
390 : :
391 : : void
392 : 24367 : spdk_trace_add_register_fn(struct spdk_trace_register_fn *reg_fn)
393 : : {
394 : : struct spdk_trace_register_fn *_reg_fn;
395 : :
396 [ + + + - : 24367 : if (reg_fn->name == NULL) {
+ - ]
397 : 0 : SPDK_ERRLOG("missing name for registering spdk trace tpoint group\n");
398 [ # # ]: 0 : assert(false);
399 : : return;
400 : : }
401 : :
402 [ + + + + : 24367 : if (strcmp(reg_fn->name, "all") == 0) {
+ - + - +
- ]
403 [ # # # # ]: 0 : SPDK_ERRLOG("illegal name (%s) for tpoint group\n", reg_fn->name);
404 [ # # ]: 0 : assert(false);
405 : : return;
406 : : }
407 : :
408 : : /* Ensure that no trace point group IDs and names are ever duplicated */
409 [ + + + - : 127742 : for (_reg_fn = g_reg_fn_head; _reg_fn; _reg_fn = _reg_fn->next) {
+ - ]
410 [ + + + - : 103375 : if (reg_fn->tgroup_id == _reg_fn->tgroup_id) {
+ - + - +
- ]
411 [ # # # # : 0 : SPDK_ERRLOG("group %d, %s has duplicate tgroup_id with %s\n",
# # # # #
# # # ]
412 : : reg_fn->tgroup_id, reg_fn->name, _reg_fn->name);
413 [ # # ]: 0 : assert(false);
414 : : return;
415 : : }
416 : :
417 [ + + + + : 103375 : if (strcmp(reg_fn->name, _reg_fn->name) == 0) {
+ + + - +
- + - +
- ]
418 [ # # # # : 0 : SPDK_ERRLOG("name %s is duplicated between groups with ids %d and %d\n",
# # # # #
# # # ]
419 : : reg_fn->name, reg_fn->tgroup_id, _reg_fn->tgroup_id);
420 [ # # ]: 0 : assert(false);
421 : : return;
422 : : }
423 : 3977 : }
424 : :
425 : : /* Arrange trace registration in order on tgroup_id */
426 [ + + + + : 24367 : if (g_reg_fn_head == NULL || reg_fn->tgroup_id < g_reg_fn_head->tgroup_id) {
+ - + - +
- + + ]
427 [ + - + - ]: 8719 : reg_fn->next = g_reg_fn_head;
428 : 8719 : g_reg_fn_head = reg_fn;
429 : 8719 : return;
430 : : }
431 : :
432 [ + + + - : 56855 : for (_reg_fn = g_reg_fn_head; _reg_fn; _reg_fn = _reg_fn->next) {
+ - ]
433 [ + + + + : 56855 : if (_reg_fn->next == NULL || reg_fn->tgroup_id < _reg_fn->next->tgroup_id) {
+ + + - +
- + - + -
+ - + - +
+ ]
434 [ + - + - : 15648 : reg_fn->next = _reg_fn->next;
+ - + - ]
435 [ + - + - ]: 15648 : _reg_fn->next = reg_fn;
436 : 15648 : return;
437 : : }
438 : 1173 : }
439 : 823 : }
440 : :
441 : : void
442 : 2893 : spdk_trace_flags_init(void)
443 : : {
444 : : struct spdk_trace_register_fn *reg_fn;
445 : :
446 : 2893 : reg_fn = g_reg_fn_head;
447 [ + + ]: 24844 : while (reg_fn) {
448 [ + - + - : 21951 : reg_fn->reg_fn();
- + - + ]
449 [ + - + - ]: 21951 : reg_fn = reg_fn->next;
450 : : }
451 : 2893 : }
|