]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/lib/trace/trace_flags.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / lib / trace / trace_flags.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "spdk/stdinc.h"
35
36 #include "spdk/env.h"
37 #include "spdk/trace.h"
38 #include "spdk/log.h"
39 #include "spdk_internal/log.h"
40
41 struct spdk_trace_flags *g_trace_flags = NULL;
42 static struct spdk_trace_register_fn *g_reg_fn_head = NULL;
43
44 SPDK_LOG_REGISTER_COMPONENT("trace", SPDK_LOG_TRACE)
45
46 uint64_t
47 spdk_trace_get_tpoint_mask(uint32_t group_id)
48 {
49 if (group_id >= SPDK_TRACE_MAX_GROUP_ID) {
50 SPDK_ERRLOG("%s: invalid group ID %d\n", __func__, group_id);
51 return 0ULL;
52 }
53
54 return g_trace_flags->tpoint_mask[group_id];
55 }
56
57 void
58 spdk_trace_set_tpoints(uint32_t group_id, uint64_t tpoint_mask)
59 {
60 if (group_id >= SPDK_TRACE_MAX_GROUP_ID) {
61 SPDK_ERRLOG("%s: invalid group ID %d\n", __func__, group_id);
62 return;
63 }
64
65 g_trace_flags->tpoint_mask[group_id] |= tpoint_mask;
66 }
67
68 void
69 spdk_trace_clear_tpoints(uint32_t group_id, uint64_t tpoint_mask)
70 {
71 if (group_id >= SPDK_TRACE_MAX_GROUP_ID) {
72 SPDK_ERRLOG("%s: invalid group ID %d\n", __func__, group_id);
73 return;
74 }
75
76 g_trace_flags->tpoint_mask[group_id] &= ~tpoint_mask;
77 }
78
79 uint64_t
80 spdk_trace_get_tpoint_group_mask(void)
81 {
82 uint64_t mask = 0x0;
83 int i;
84
85 for (i = 0; i < SPDK_TRACE_MAX_GROUP_ID; i++) {
86 if (spdk_trace_get_tpoint_mask(i) != 0) {
87 mask |= (1ULL << i);
88 }
89 }
90
91 return mask;
92 }
93
94 void
95 spdk_trace_set_tpoint_group_mask(uint64_t tpoint_group_mask)
96 {
97 int i;
98
99 for (i = 0; i < SPDK_TRACE_MAX_GROUP_ID; i++) {
100 if (tpoint_group_mask & (1ULL << i)) {
101 spdk_trace_set_tpoints(i, -1ULL);
102 }
103 }
104 }
105
106 void
107 spdk_trace_clear_tpoint_group_mask(uint64_t tpoint_group_mask)
108 {
109 int i;
110
111 for (i = 0; i < SPDK_TRACE_MAX_GROUP_ID; i++) {
112 if (tpoint_group_mask & (1ULL << i)) {
113 spdk_trace_clear_tpoints(i, -1ULL);
114 }
115 }
116 }
117
118 struct spdk_trace_register_fn *
119 spdk_trace_get_first_register_fn(void)
120 {
121 return g_reg_fn_head;
122 }
123
124 struct spdk_trace_register_fn *
125 spdk_trace_get_next_register_fn(struct spdk_trace_register_fn *register_fn)
126 {
127 return register_fn->next;
128 }
129
130 static uint64_t
131 trace_create_tpoint_group_mask(const char *group_name)
132 {
133 uint64_t tpoint_group_mask = 0;
134 struct spdk_trace_register_fn *register_fn;
135
136 register_fn = spdk_trace_get_first_register_fn();
137 if (strcmp(group_name, "all") == 0) {
138 while (register_fn) {
139 tpoint_group_mask |= (1UL << register_fn->tgroup_id);
140
141 register_fn = spdk_trace_get_next_register_fn(register_fn);
142 }
143 } else {
144 while (register_fn) {
145 if (strcmp(group_name, register_fn->name) == 0) {
146 break;
147 }
148
149 register_fn = spdk_trace_get_next_register_fn(register_fn);
150 }
151
152 if (register_fn != NULL) {
153 tpoint_group_mask |= (1UL << register_fn->tgroup_id);
154 }
155 }
156
157 return tpoint_group_mask;
158 }
159
160 int
161 spdk_trace_enable_tpoint_group(const char *group_name)
162 {
163 uint64_t tpoint_group_mask = 0;
164
165 tpoint_group_mask = trace_create_tpoint_group_mask(group_name);
166 if (tpoint_group_mask == 0) {
167 return -1;
168 }
169
170 spdk_trace_set_tpoint_group_mask(tpoint_group_mask);
171 return 0;
172 }
173
174 int
175 spdk_trace_disable_tpoint_group(const char *group_name)
176 {
177 uint64_t tpoint_group_mask = 0;
178
179 tpoint_group_mask = trace_create_tpoint_group_mask(group_name);
180 if (tpoint_group_mask == 0) {
181 return -1;
182 }
183
184 spdk_trace_clear_tpoint_group_mask(tpoint_group_mask);
185 return 0;
186 }
187
188 void
189 spdk_trace_mask_usage(FILE *f, const char *tmask_arg)
190 {
191 struct spdk_trace_register_fn *register_fn;
192
193 fprintf(f, " %s, --tpoint-group-mask <mask>\n", tmask_arg);
194 fprintf(f, " tracepoint group mask for spdk trace buffers (default 0x0");
195
196 register_fn = g_reg_fn_head;
197 while (register_fn) {
198 fprintf(f, ", %s 0x%x", register_fn->name, 1 << register_fn->tgroup_id);
199 register_fn = register_fn->next;
200 }
201
202 fprintf(f, ", all 0xffff)\n");
203 }
204
205 void
206 spdk_trace_register_owner(uint8_t type, char id_prefix)
207 {
208 struct spdk_trace_owner *owner;
209
210 assert(type != OWNER_NONE);
211
212 /* 'owner' has 256 entries and since 'type' is a uint8_t, it
213 * can't overrun the array.
214 */
215 owner = &g_trace_flags->owner[type];
216 assert(owner->type == 0);
217
218 owner->type = type;
219 owner->id_prefix = id_prefix;
220 }
221
222 void
223 spdk_trace_register_object(uint8_t type, char id_prefix)
224 {
225 struct spdk_trace_object *object;
226
227 assert(type != OBJECT_NONE);
228
229 /* 'object' has 256 entries and since 'type' is a uint8_t, it
230 * can't overrun the array.
231 */
232 object = &g_trace_flags->object[type];
233 assert(object->type == 0);
234
235 object->type = type;
236 object->id_prefix = id_prefix;
237 }
238
239 void
240 spdk_trace_register_description(const char *name, uint16_t tpoint_id, uint8_t owner_type,
241 uint8_t object_type, uint8_t new_object,
242 uint8_t arg1_type, const char *arg1_name)
243 {
244 struct spdk_trace_tpoint *tpoint;
245
246 assert(tpoint_id != 0);
247 assert(tpoint_id < SPDK_TRACE_MAX_TPOINT_ID);
248
249 if (strnlen(name, sizeof(tpoint->name)) == sizeof(tpoint->name)) {
250 SPDK_ERRLOG("name (%s) too long\n", name);
251 }
252
253 tpoint = &g_trace_flags->tpoint[tpoint_id];
254 assert(tpoint->tpoint_id == 0);
255
256 snprintf(tpoint->name, sizeof(tpoint->name), "%s", name);
257 tpoint->tpoint_id = tpoint_id;
258 tpoint->object_type = object_type;
259 tpoint->owner_type = owner_type;
260 tpoint->new_object = new_object;
261 tpoint->arg1_type = arg1_type;
262 snprintf(tpoint->arg1_name, sizeof(tpoint->arg1_name), "%s", arg1_name);
263 }
264
265 void
266 spdk_trace_add_register_fn(struct spdk_trace_register_fn *reg_fn)
267 {
268 struct spdk_trace_register_fn *_reg_fn;
269
270 if (reg_fn->name == NULL) {
271 SPDK_ERRLOG("missing name for registering spdk trace tpoint group\n");
272 assert(false);
273 return;
274 }
275
276 if (strcmp(reg_fn->name, "all") == 0) {
277 SPDK_ERRLOG("illegal name (%s) for tpoint group\n", reg_fn->name);
278 assert(false);
279 return;
280 }
281
282 /* Ensure that no trace point group IDs and names are ever duplicated */
283 for (_reg_fn = g_reg_fn_head; _reg_fn; _reg_fn = _reg_fn->next) {
284 if (reg_fn->tgroup_id == _reg_fn->tgroup_id) {
285 SPDK_ERRLOG("duplicate tgroup_id (%d) with %s\n", _reg_fn->tgroup_id, _reg_fn->name);
286 assert(false);
287 return;
288 }
289
290 if (strcmp(reg_fn->name, _reg_fn->name) == 0) {
291 SPDK_ERRLOG("duplicate name with %s\n", _reg_fn->name);
292 assert(false);
293 return;
294 }
295 }
296
297 /* Arrange trace registration in order on tgroup_id */
298 if (g_reg_fn_head == NULL || reg_fn->tgroup_id < g_reg_fn_head->tgroup_id) {
299 reg_fn->next = g_reg_fn_head;
300 g_reg_fn_head = reg_fn;
301 return;
302 }
303
304 for (_reg_fn = g_reg_fn_head; _reg_fn; _reg_fn = _reg_fn->next) {
305 if (_reg_fn->next == NULL || reg_fn->tgroup_id < _reg_fn->next->tgroup_id) {
306 reg_fn->next = _reg_fn->next;
307 _reg_fn->next = reg_fn;
308 return;
309 }
310 }
311 }
312
313 void
314 spdk_trace_flags_init(void)
315 {
316 struct spdk_trace_register_fn *reg_fn;
317
318 reg_fn = g_reg_fn_head;
319 while (reg_fn) {
320 reg_fn->reg_fn();
321 reg_fn = reg_fn->next;
322 }
323 }